1
0
cuberite-2a/src/DeadlockDetect.cpp

148 lines
2.4 KiB
C++
Raw Normal View History

// DeadlockDetect.cpp
// Declares the cDeadlockDetect class that tries to detect deadlocks and aborts the server when it detects one
#include "Globals.h"
#include "DeadlockDetect.h"
#include "Root.h"
#include "World.h"
#include <cstdlib>
/** Number of milliseconds per cycle */
2014-10-23 18:58:01 -04:00
const int CYCLE_MILLISECONDS = 100;
cDeadlockDetect::cDeadlockDetect(void) :
super("DeadlockDetect"),
m_IntervalSec(1000)
{
}
bool cDeadlockDetect::Start(int a_IntervalSec)
{
m_IntervalSec = a_IntervalSec;
2016-02-05 16:45:45 -05:00
// Read the initial world data:
class cFillIn :
public cWorldListCallback
{
public:
cFillIn(cDeadlockDetect * a_Detect) :
m_Detect(a_Detect)
{
}
2016-02-05 16:45:45 -05:00
virtual bool Item(cWorld * a_World) override
{
m_Detect->SetWorldAge(a_World->GetName(), a_World->GetWorldAge());
return false;
}
2016-02-05 16:45:45 -05:00
protected:
cDeadlockDetect * m_Detect;
} FillIn(this);
cRoot::Get()->ForEachWorld(FillIn);
return super::Start();
}
void cDeadlockDetect::Execute(void)
{
// Loop until the signal to terminate:
while (!m_ShouldTerminate)
{
// Check the world ages:
class cChecker :
public cWorldListCallback
{
public:
cChecker(cDeadlockDetect * a_Detect) :
m_Detect(a_Detect)
{
}
2016-02-05 16:45:45 -05:00
protected:
cDeadlockDetect * m_Detect;
2016-02-05 16:45:45 -05:00
virtual bool Item(cWorld * a_World) override
{
m_Detect->CheckWorldAge(a_World->GetName(), a_World->GetWorldAge());
return false;
}
} Checker(this);
cRoot::Get()->ForEachWorld(Checker);
2016-02-05 16:45:45 -05:00
std::this_thread::sleep_for(std::chrono::milliseconds(CYCLE_MILLISECONDS));
} // while (should run)
}
void cDeadlockDetect::SetWorldAge(const AString & a_WorldName, Int64 a_Age)
{
m_WorldAges[a_WorldName].m_Age = a_Age;
m_WorldAges[a_WorldName].m_NumCyclesSame = 0;
}
void cDeadlockDetect::CheckWorldAge(const AString & a_WorldName, Int64 a_Age)
{
WorldAges::iterator itr = m_WorldAges.find(a_WorldName);
if (itr == m_WorldAges.end())
{
SetWorldAge(a_WorldName, a_Age);
return;
}
cDeadlockDetect::sWorldAge & WorldAge = itr->second;
if (WorldAge.m_Age == a_Age)
{
WorldAge.m_NumCyclesSame += 1;
if (WorldAge.m_NumCyclesSame > (m_IntervalSec * 1000) / CYCLE_MILLISECONDS)
{
DeadlockDetected();
}
}
else
{
WorldAge.m_Age = a_Age;
WorldAge.m_NumCyclesSame = 0;
}
}
void cDeadlockDetect::DeadlockDetected(void)
{
LOGERROR("Deadlock detected, aborting the server");
ASSERT(!"Deadlock detected");
abort();
}