summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Root.cpp34
-rw-r--r--src/main.cpp64
2 files changed, 78 insertions, 20 deletions
diff --git a/src/Root.cpp b/src/Root.cpp
index fffd8fb47..798f965be 100644
--- a/src/Root.cpp
+++ b/src/Root.cpp
@@ -22,6 +22,7 @@
#include "inifile/iniFile.h"
#ifdef _WIN32
+ #include "conio.h"
#include <psapi.h>
#elif defined(__linux__)
#include <fstream>
@@ -29,6 +30,8 @@
#include <mach/mach.h>
#endif
+extern bool g_TERMINATE_EVENT_RAISED;
+
@@ -76,7 +79,7 @@ void cRoot::InputThread(void * a_Params)
cLogCommandOutputCallback Output;
- while (!(self.m_bStop || self.m_bRestart) && std::cin.good())
+ while (!self.m_bStop && !self.m_bRestart && !g_TERMINATE_EVENT_RAISED && std::cin.good())
{
AString Command;
std::getline(std::cin, Command);
@@ -85,10 +88,10 @@ void cRoot::InputThread(void * a_Params)
self.ExecuteConsoleCommand(TrimString(Command), Output);
}
}
-
- if (!(self.m_bStop || self.m_bRestart))
+
+ if (g_TERMINATE_EVENT_RAISED || !std::cin.good())
{
- // We have come here because the std::cin has received an EOF and the server is still running; stop the server:
+ // We have come here because the std::cin has received an EOF / a terminate signal has been sent, and the server is still running; stop the server:
self.m_bStop = true;
}
}
@@ -99,6 +102,12 @@ void cRoot::InputThread(void * a_Params)
void cRoot::Start(void)
{
+ #ifdef _WIN32
+ HWND hwnd = GetConsoleWindow();
+ HMENU hmenu = GetSystemMenu(hwnd, FALSE);
+ EnableMenuItem(hmenu, SC_CLOSE, MF_GRAYED); // Disable close button when starting up; it causes problems with our CTRL-CLOSE handling
+ #endif
+
cDeadlockDetect dd;
delete m_Log;
m_Log = new cMCLogger();
@@ -192,12 +201,20 @@ void cRoot::Start(void)
finishmseconds -= mseconds;
LOG("Startup complete, took %i ms!", finishmseconds);
+ #ifdef _WIN32
+ EnableMenuItem(hmenu, SC_CLOSE, MF_ENABLED); // Re-enable close button
+ #endif
- while (!m_bStop && !m_bRestart) // These are modified by external threads
+ while (!m_bStop && !m_bRestart && !g_TERMINATE_EVENT_RAISED) // These are modified by external threads
{
cSleep::MilliSleep(1000);
}
+ if (g_TERMINATE_EVENT_RAISED)
+ {
+ m_bStop = true;
+ }
+
#if !defined(ANDROID_NDK)
delete m_InputThread; m_InputThread = NULL;
#endif
@@ -222,7 +239,7 @@ void cRoot::Start(void)
delete m_FurnaceRecipe; m_FurnaceRecipe = NULL;
delete m_CraftingRecipes; m_CraftingRecipes = NULL;
LOGD("Forgetting groups...");
- delete m_GroupManager; m_GroupManager = 0;
+ delete m_GroupManager; m_GroupManager = NULL;
LOGD("Unloading worlds...");
UnloadWorlds();
@@ -233,12 +250,11 @@ void cRoot::Start(void)
cBlockHandler::Deinit();
LOG("Cleaning up...");
- //delete HeartBeat; HeartBeat = 0;
- delete m_Server; m_Server = 0;
+ delete m_Server; m_Server = NULL;
LOG("Shutdown successful!");
}
- delete m_Log; m_Log = 0;
+ delete m_Log; m_Log = NULL;
}
diff --git a/src/main.cpp b/src/main.cpp
index 1f6aad24f..84339b8d6 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -11,6 +11,10 @@
#include <dbghelp.h>
#endif // _MSC_VER
+// Here, we have some ALL CAPS variables, to give the impression that this is deeeep, gritty programming :P
+bool g_TERMINATE_EVENT_RAISED = false; // If something has told the server to stop; checked periodically in cRoot
+bool g_SERVER_TERMINATED = false; // Set to true when the server terminates, so our CTRL handler can then tell Windows to close the console
+
@@ -33,14 +37,21 @@
-
-void ShowCrashReport(int)
+void NonCtrlHandler(int a_Signal)
{
- std::signal(SIGSEGV, SIG_DFL);
+ LOGD("Terminate event raised from std::signal");
+ g_TERMINATE_EVENT_RAISED = true;
- printf("\n\nMCServer has crashed!\n");
-
- exit(-1);
+ switch (a_Signal)
+ {
+ case SIGSEGV:
+ {
+ std::signal(SIGSEGV, SIG_DFL);
+ LOGWARN("Segmentation fault; MCServer has crashed :(");
+ exit(EXIT_FAILURE);
+ }
+ default: break;
+ }
}
@@ -111,13 +122,33 @@ LONG WINAPI LastChanceExceptionFilter(__in struct _EXCEPTION_POINTERS * a_Except
+#ifdef _WIN32
+// Handle CTRL events in windows, including console window close
+BOOL CtrlHandler(DWORD fdwCtrlType)
+{
+ g_TERMINATE_EVENT_RAISED = true;
+ LOGD("Terminate event raised from the Windows CtrlHandler");
+
+ if (fdwCtrlType == CTRL_CLOSE_EVENT)
+ {
+ while (!g_SERVER_TERMINATED) { cSleep::MilliSleep(100); } // Delay as much as possible to try to get the server to shut down cleanly
+ }
+
+ return TRUE;
+}
+#endif
+
+
+
+
+
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// main:
int main( int argc, char **argv )
{
- (void)argc;
- (void)argv;
+ UNUSED(argc);
+ UNUSED(argv);
#if defined(_MSC_VER) && defined(_DEBUG) && defined(ENABLE_LEAK_FINDER)
InitLeakFinder();
@@ -149,6 +180,13 @@ int main( int argc, char **argv )
}
#endif // _WIN32 && !_WIN64
// End of dump-file magic
+
+ #ifdef _WIN32
+ if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE))
+ {
+ LOGERROR("Could not install the Windows CTRL handler!");
+ }
+ #endif
#if defined(_DEBUG) && defined(_MSC_VER)
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
@@ -160,7 +198,9 @@ int main( int argc, char **argv )
#endif // _DEBUG && _MSC_VER
#ifndef _DEBUG
- std::signal(SIGSEGV, ShowCrashReport);
+ std::signal(SIGSEGV, NonCtrlHandler);
+ std::signal(SIGTERM, NonCtrlHandler);
+ std::signal(SIGINT, NonCtrlHandler);
#endif
// DEBUG: test the dumpfile creation:
@@ -188,8 +228,10 @@ int main( int argc, char **argv )
#if defined(_MSC_VER) && defined(_DEBUG) && defined(ENABLE_LEAK_FINDER)
DeinitLeakFinder();
#endif
-
- return 0;
+
+ g_SERVER_TERMINATED = true;
+
+ return EXIT_SUCCESS;
}