summaryrefslogtreecommitdiffstats
path: root/src/OSSupport/ConsoleSignalHandler.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/OSSupport/ConsoleSignalHandler.h')
-rw-r--r--src/OSSupport/ConsoleSignalHandler.h130
1 files changed, 130 insertions, 0 deletions
diff --git a/src/OSSupport/ConsoleSignalHandler.h b/src/OSSupport/ConsoleSignalHandler.h
new file mode 100644
index 000000000..23e63d555
--- /dev/null
+++ b/src/OSSupport/ConsoleSignalHandler.h
@@ -0,0 +1,130 @@
+
+// ConsoleSignalHandler.h
+
+// Intercepts signals for graceful CTRL-C (and others) handling.
+
+// This file MUST NOT be included from anywhere other than main.cpp.
+
+
+
+
+
+#include <csignal>
+
+
+
+
+
+// Because SIG_DFL or SIG_IGN could be NULL instead of nullptr, we need to disable the Clang warning here:
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunknown-warning-option"
+#pragma clang diagnostic ignored "-Wunknown-pragmas"
+#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
+#endif
+
+static void NonCtrlHandler(int a_Signal)
+{
+ LOGD("Terminate event raised from std::signal");
+
+ switch (a_Signal)
+ {
+ case SIGSEGV:
+ {
+ PrintStackTrace();
+
+ LOGERROR(
+ "Failure report: \n\n"
+ " :( | Cuberite has encountered an error and needs to close\n"
+ " | SIGSEGV: Segmentation fault\n"
+ " |\n"
+#ifdef BUILD_ID
+ " | Cuberite " BUILD_SERIES_NAME " (id: " BUILD_ID ")\n"
+ " | from commit " BUILD_COMMIT_ID "\n"
+#endif
+ );
+
+ std::signal(SIGSEGV, SIG_DFL);
+ return;
+ }
+ case SIGABRT:
+#ifdef SIGABRT_COMPAT
+ case SIGABRT_COMPAT:
+#endif
+ {
+ PrintStackTrace();
+
+ LOGERROR(
+ "Failure report: \n\n"
+ " :( | Cuberite has encountered an error and needs to close\n"
+ " | SIGABRT: Server self-terminated due to an internal fault\n"
+ " |\n"
+#ifdef BUILD_ID
+ " | Cuberite " BUILD_SERIES_NAME " (id: " BUILD_ID ")\n"
+ " | from commit " BUILD_COMMIT_ID "\n"
+#endif
+ );
+
+ std::signal(SIGSEGV, SIG_DFL);
+ return;
+ }
+ case SIGINT:
+ case SIGTERM:
+ {
+ // Server is shutting down, wait for it...
+ cRoot::Stop();
+ return;
+ }
+ }
+}
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+
+
+
+
+#ifdef _WIN32
+
+/** Handle CTRL events in windows, including console window close. */
+static BOOL CtrlHandler(DWORD fdwCtrlType)
+{
+ cRoot::Stop();
+ LOGD("Terminate event raised from the Windows CtrlHandler");
+
+ // Delay as much as possible to try to get the server to shut down cleanly - 10 seconds given by Windows:
+ std::this_thread::sleep_for(std::chrono::seconds(10));
+
+ // Returning from main() automatically aborts this handler thread.
+
+ return TRUE;
+}
+
+#endif
+
+
+
+
+
+namespace ConsoleSignalHandler
+{
+ static void Register()
+ {
+ std::signal(SIGSEGV, NonCtrlHandler);
+ std::signal(SIGTERM, NonCtrlHandler);
+ std::signal(SIGINT, NonCtrlHandler);
+ std::signal(SIGABRT, NonCtrlHandler);
+#ifdef SIGABRT_COMPAT
+ std::signal(SIGABRT_COMPAT, NonCtrlHandler);
+#endif
+#ifdef SIGPIPE
+ std::signal(SIGPIPE, SIG_IGN); // Ignore (PR #2487).
+#endif
+
+#ifdef _WIN32
+ SetConsoleCtrlHandler(reinterpret_cast<PHANDLER_ROUTINE>(CtrlHandler), TRUE);
+#endif
+ }
+};