add handling for sigabrt in the status file (#19769)
* add handling for sigabrt * remove empty statement warning
Costa Tsaousis committed
Mar 4, 2025 at 19:04 UTC
e30c3a52d140d7c22ddf32bb49b5431ea7ace05a
5 files changed
+30
-24
src/daemon/daemon-status-file.c
+2
-1
@@ -1116,7 +1116,8 @@ void daemon_status_file_deadly_signal_received(EXIT_REASON reason) {
1116
// save what we know already
1117
daemon_status_file_save(static_save_buffer, &session_status, false);
1118
1119
- if(!session_status.fatal.stack_trace[0]) {
1119
+ // we cannot get a stack trace on SIGABRT - it may deadlock forever
1120
+ if(reason != EXIT_REASON_SIGABRT && !session_status.fatal.stack_trace[0]) {
1121
buffer_flush(static_save_buffer);
1122
capture_stack_trace(static_save_buffer);
1123
strncpyz(session_status.fatal.stack_trace, buffer_tostring(static_save_buffer), sizeof(session_status.fatal.stack_trace) - 1);
src/daemon/main.c
+2
-2
@@ -185,7 +185,7 @@ int help(int exitcode) {
185
*/
186
187
#define delta_startup_time(msg) \
188
- { \
188
+ do { \
189
usec_t now_ut = now_monotonic_usec(); \
190
if(prev_msg) \
191
netdata_log_info("NETDATA STARTUP: in %7llu ms, %s - next: %s", (now_ut - last_ut) / USEC_PER_MS, prev_msg, msg); \
@@ -194,7 +194,7 @@ int help(int exitcode) {
194
last_ut = now_ut; \
195
prev_msg = msg; \
196
daemon_status_file_startup_step("startup(" msg ")"); \
197
- }
197
+ } while(0)
198
199
int buffer_unittest(void);
200
int pgc_unittest(void);
src/daemon/signals.c
+11
-8
@@ -9,7 +9,7 @@ typedef enum signal_action {
9
NETDATA_SIGNAL_EXIT_CLEANLY,
10
NETDATA_SIGNAL_REOPEN_LOGS,
11
NETDATA_SIGNAL_RELOAD_HEALTH,
12
- NETDATA_SIGNAL_FATAL,
12
+ NETDATA_SIGNAL_DEADLY,
13
} SIGNAL_ACTION;
14
15
static struct {
@@ -25,10 +25,11 @@ static struct {
25
{ SIGTERM, "SIGTERM", 0, NETDATA_SIGNAL_EXIT_CLEANLY, EXIT_REASON_SIGTERM },
26
{ SIGHUP, "SIGHUP", 0, NETDATA_SIGNAL_REOPEN_LOGS, EXIT_REASON_NONE },
27
{ SIGUSR2, "SIGUSR2", 0, NETDATA_SIGNAL_RELOAD_HEALTH, EXIT_REASON_NONE },
28
- { SIGBUS, "SIGBUS", 0, NETDATA_SIGNAL_FATAL, EXIT_REASON_SIGBUS },
29
- { SIGSEGV, "SIGSEGV", 0, NETDATA_SIGNAL_FATAL, EXIT_REASON_SIGSEGV },
30
- { SIGFPE, "SIGFPE", 0, NETDATA_SIGNAL_FATAL, EXIT_REASON_SIGFPE },
31
- { SIGILL, "SIGILL", 0, NETDATA_SIGNAL_FATAL, EXIT_REASON_SIGILL },
28
+ { SIGBUS, "SIGBUS", 0, NETDATA_SIGNAL_DEADLY, EXIT_REASON_SIGBUS },
29
+ { SIGSEGV, "SIGSEGV", 0, NETDATA_SIGNAL_DEADLY, EXIT_REASON_SIGSEGV },
30
+ { SIGFPE, "SIGFPE", 0, NETDATA_SIGNAL_DEADLY, EXIT_REASON_SIGFPE },
31
+ { SIGILL, "SIGILL", 0, NETDATA_SIGNAL_DEADLY, EXIT_REASON_SIGILL },
32
+ { SIGABRT, "SIGABRT", 0, NETDATA_SIGNAL_DEADLY, EXIT_REASON_SIGABRT },
33
34
// terminator
35
{ 0, "NONE", 0, NETDATA_SIGNAL_END_OF_LIST, 0 }
@@ -46,7 +47,7 @@ static void signal_handler(int signo) {
47
if(unlikely(signals_waiting[i].signo == signo)) {
48
signals_waiting[i].count++;
49
49
- if(signals_waiting[i].action == NETDATA_SIGNAL_FATAL) {
50
+ if(signals_waiting[i].action == NETDATA_SIGNAL_DEADLY) {
51
// Update the status file
52
daemon_status_file_deadly_signal_received(signals_waiting[i].reason);
53
@@ -61,6 +62,7 @@ static void signal_handler(int signo) {
62
}
63
64
// Reset the signal's disposition to the default handler.
65
+
66
struct sigaction sa;
67
sa.sa_handler = SIG_DFL;
68
sigemptyset(&sa.sa_mask);
@@ -91,6 +93,7 @@ static void posix_signals_default_mask(void) {
93
sigdelset(&sigset, SIGSEGV);
94
sigdelset(&sigset, SIGFPE);
95
sigdelset(&sigset, SIGILL);
96
+ sigdelset(&sigset, SIGABRT);
97
98
if(pthread_sigmask(SIG_BLOCK, &sigset, NULL) != 0)
99
netdata_log_error("SIGNAL: cannot apply the default mask for signals");
@@ -184,10 +187,10 @@ void nd_process_signals(void) {
187
exit(0);
188
break;
189
187
- case NETDATA_SIGNAL_FATAL:
190
+ case NETDATA_SIGNAL_DEADLY:
191
nd_log_limits_unlimited();
192
daemon_status_file_deadly_signal_received(signals_waiting[i].reason);
190
- fatal("SIGNAL: Received %s. netdata now exits.", name);
193
+ _exit(1);
194
break;
195
196
default:
src/libnetdata/exit/exit_initiated.c
+1
@@ -9,6 +9,7 @@ ENUM_STR_MAP_DEFINE(EXIT_REASON) = {
9
{ EXIT_REASON_SIGSEGV, "signal-segmentation-fault"},
10
{ EXIT_REASON_SIGFPE, "signal-floating-point-exception"},
11
{ EXIT_REASON_SIGILL, "signal-illegal-instruction"},
12
+ { EXIT_REASON_SIGABRT, "signal-abort"},
13
{ EXIT_REASON_OUT_OF_MEMORY, "out-of-memory"},
14
{ EXIT_REASON_ALREADY_RUNNING, "already-running"},
15
src/libnetdata/exit/exit_initiated.h
+14
-13
@@ -14,36 +14,37 @@ typedef enum {
14
EXIT_REASON_SIGSEGV = (1 << 1),
15
EXIT_REASON_SIGFPE = (1 << 2),
16
EXIT_REASON_SIGILL = (1 << 3),
17
- EXIT_REASON_OUT_OF_MEMORY = (1 << 4),
18
- EXIT_REASON_ALREADY_RUNNING = (1 << 5),
17
+ EXIT_REASON_SIGABRT = (1 << 4),
18
+ EXIT_REASON_OUT_OF_MEMORY = (1 << 5),
19
+ EXIT_REASON_ALREADY_RUNNING = (1 << 6),
20
21
// abnormal termination via a fatal message
21
- EXIT_REASON_FATAL = (1 << 6), // a fatal message
22
+ EXIT_REASON_FATAL = (1 << 7), // a fatal message
23
24
// normal termination via APIs
24
- EXIT_REASON_API_QUIT = (1 << 7), // developer only
25
- EXIT_REASON_CMD_EXIT = (1 << 8), // netdatacli
25
+ EXIT_REASON_API_QUIT = (1 << 8), // developer only
26
+ EXIT_REASON_CMD_EXIT = (1 << 9), // netdatacli
27
28
// signals - normal termination
28
- EXIT_REASON_SIGQUIT = (1 << 9), // rare, but graceful
29
- EXIT_REASON_SIGTERM = (1 << 10), // received on Linux, FreeBSD, MacOS
30
- EXIT_REASON_SIGINT = (1 << 11), // received on Windows on normal termination
29
+ EXIT_REASON_SIGQUIT = (1 << 10), // rare, but graceful
30
+ EXIT_REASON_SIGTERM = (1 << 11), // received on Linux, FreeBSD, MacOS
31
+ EXIT_REASON_SIGINT = (1 << 12), // received on Windows on normal termination
32
33
// windows specific, service stop
33
- EXIT_REASON_SERVICE_STOP = (1 << 12),
34
+ EXIT_REASON_SERVICE_STOP = (1 << 13),
35
36
// automatically detect when exit_initiated_set() is called
37
// supports Linux, FreeBSD, MacOS, Windows
37
- EXIT_REASON_SYSTEM_SHUTDOWN = (1 << 13),
38
+ EXIT_REASON_SYSTEM_SHUTDOWN = (1 << 14),
39
40
// netdata update
40
- EXIT_REASON_UPDATE = (1 << 14),
41
+ EXIT_REASON_UPDATE = (1 << 15),
42
} EXIT_REASON;
43
44
#define EXIT_REASON_NORMAL (EXIT_REASON_SIGINT|EXIT_REASON_SIGTERM|EXIT_REASON_SIGQUIT|EXIT_REASON_API_QUIT|EXIT_REASON_CMD_EXIT|EXIT_REASON_SERVICE_STOP|EXIT_REASON_SYSTEM_SHUTDOWN|EXIT_REASON_UPDATE)
44
-#define EXIT_REASON_ABNORMAL (EXIT_REASON_SIGBUS|EXIT_REASON_SIGSEGV|EXIT_REASON_SIGFPE|EXIT_REASON_SIGILL|EXIT_REASON_FATAL|EXIT_REASON_OUT_OF_MEMORY)
45
+#define EXIT_REASON_ABNORMAL (EXIT_REASON_SIGBUS|EXIT_REASON_SIGSEGV|EXIT_REASON_SIGFPE|EXIT_REASON_SIGILL|EXIT_REASON_SIGABRT|EXIT_REASON_FATAL|EXIT_REASON_OUT_OF_MEMORY)
46
46
-#define is_deadly_signal(reason) ((reason) & (EXIT_REASON_SIGBUS|EXIT_REASON_SIGSEGV|EXIT_REASON_SIGFPE|EXIT_REASON_SIGILL))
47
+#define is_deadly_signal(reason) ((reason) & (EXIT_REASON_SIGBUS|EXIT_REASON_SIGSEGV|EXIT_REASON_SIGFPE|EXIT_REASON_SIGILL|EXIT_REASON_SIGABRT))
48
#define is_exit_reason_normal(reason) (((reason) & EXIT_REASON_NORMAL) && !((reason) & EXIT_REASON_ABNORMAL))
49
50
typedef struct web_buffer BUFFER;