Cuberite
A lightweight, fast and extensible game server for Minecraft
ConsoleSignalHandler.h
Go to the documentation of this file.
1 
2 // ConsoleSignalHandler.h
3 
4 // Intercepts signals for graceful CTRL-C (and others) handling.
5 
6 // This file MUST NOT be included from anywhere other than main.cpp.
7 
8 
9 
10 
11 
12 #include <csignal>
13 
14 
15 
16 
17 
18 // Because SIG_DFL or SIG_IGN could be NULL instead of nullptr, we need to disable the Clang warning here:
19 #ifdef __clang__
20 #pragma clang diagnostic push
21 #pragma clang diagnostic ignored "-Wunknown-warning-option"
22 #pragma clang diagnostic ignored "-Wunknown-pragmas"
23 #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
24 #endif
25 
26 static void NonCtrlHandler(int a_Signal)
27 {
28  LOGD("Terminate event raised from std::signal");
29 
30  switch (a_Signal)
31  {
32  case SIGSEGV:
33  {
35 
36  LOGERROR(
37  "Failure report: \n\n"
38  " :( | Cuberite has encountered an error and needs to close\n"
39  " | SIGSEGV: Segmentation fault\n"
40  " |\n"
41 #ifdef BUILD_ID
42  " | Cuberite " BUILD_SERIES_NAME " (id: " BUILD_ID ")\n"
43  " | from commit " BUILD_COMMIT_ID "\n"
44 #endif
45  );
46 
47  std::signal(SIGSEGV, SIG_DFL);
48  return;
49  }
50  case SIGABRT:
51 #ifdef SIGABRT_COMPAT
52  case SIGABRT_COMPAT:
53 #endif
54  {
56 
57  LOGERROR(
58  "Failure report: \n\n"
59  " :( | Cuberite has encountered an error and needs to close\n"
60  " | SIGABRT: Server self-terminated due to an internal fault\n"
61  " |\n"
62 #ifdef BUILD_ID
63  " | Cuberite " BUILD_SERIES_NAME " (id: " BUILD_ID ")\n"
64  " | from commit " BUILD_COMMIT_ID "\n"
65 #endif
66  );
67 
68  std::signal(SIGSEGV, SIG_DFL);
69  return;
70  }
71  case SIGINT:
72  case SIGTERM:
73  {
74  // Server is shutting down, wait for it...
75  cRoot::Stop();
76  return;
77  }
78  }
79 }
80 
81 #ifdef __clang__
82 #pragma clang diagnostic pop
83 #endif
84 
85 
86 
87 
88 
89 #ifdef _WIN32
90 
92 static BOOL CtrlHandler(DWORD fdwCtrlType)
93 {
94  cRoot::Stop();
95  LOGD("Terminate event raised from the Windows CtrlHandler");
96 
97  // Delay as much as possible to try to get the server to shut down cleanly - 10 seconds given by Windows:
98  std::this_thread::sleep_for(std::chrono::seconds(10));
99 
100  // Returning from main() automatically aborts this handler thread.
101 
102  return TRUE;
103 }
104 
105 #endif
106 
107 
108 
109 
110 
112 {
113  static void Register()
114  {
115  std::signal(SIGSEGV, NonCtrlHandler);
116  std::signal(SIGTERM, NonCtrlHandler);
117  std::signal(SIGINT, NonCtrlHandler);
118  std::signal(SIGABRT, NonCtrlHandler);
119 #ifdef SIGABRT_COMPAT
120  std::signal(SIGABRT_COMPAT, NonCtrlHandler);
121 #endif
122 #ifdef SIGPIPE
123  std::signal(SIGPIPE, SIG_IGN); // Ignore (PR #2487).
124 #endif
125 
126 #ifdef _WIN32
127  SetConsoleCtrlHandler(reinterpret_cast<PHANDLER_ROUTINE>(CtrlHandler), TRUE);
128 #endif
129  }
130 };
void LOGERROR(std::string_view a_Format, const Args &... args)
Definition: LoggerSimple.h:73
#define LOGD
Definition: LoggerSimple.h:83
static void NonCtrlHandler(int a_Signal)
void PrintStackTrace(void)
Prints the stacktrace for the current thread.
Definition: StackTrace.cpp:21
static void Stop()
Interrupts the server and stops it, as if "/stop" typed in the console.
Definition: Root.cpp:259