fix for system shutdown (#19897)
Costa Tsaousis committed
Mar 18, 2025 at 12:33 UTC
a4951c1b7f4815bdfb43fbb4c5247e263b8658f7
13 files changed
+49
-53
src/collectors/freebsd.plugin/plugin_freebsd.c
+1
-1
@@ -91,7 +91,7 @@ void *freebsd_main(void *ptr)
91
92
// initialize FreeBSD plugin
93
if (freebsd_plugin_init())
94
- netdata_cleanup_and_exit_fatal(EXIT_REASON_FATAL);
94
+ netdata_exit_fatal(EXIT_REASON_FATAL);
95
96
// check the enabled status for each module
97
int i;
src/daemon/commands.c
+1
-3
@@ -164,9 +164,7 @@ static cmd_status_t cmd_exit_execute(char *args, char **message)
164
165
nd_log_limits_unlimited();
166
netdata_log_info("COMMAND: Cleaning up to exit.");
167
- netdata_cleanup_and_exit_gracefully(EXIT_REASON_CMD_EXIT);
168
- exit(0);
169
-
167
+ netdata_exit_gracefully(EXIT_REASON_CMD_EXIT);
168
return CMD_STATUS_SUCCESS;
169
}
170
src/daemon/daemon-shutdown.c
+20
-21
@@ -171,18 +171,15 @@ static void rrdeng_flush_everything_and_wait(bool wait_flush, bool wait_collecto
171
}
172
#endif
173
174
-#if !defined(OS_WINDOWS)
175
-NORETURN
176
-#endif
177
-static void netdata_cleanup_and_exit(EXIT_REASON reason) {
174
+ND_EXIT_NORETURN
175
+static void netdata_cleanup_and_exit(EXIT_REASON reason, bool abnormal) {
176
exit_initiated_set(reason);
179
- int ret = is_exit_reason_normal(exit_initiated_get()) ? 0 : 1;
177
178
// don't recurse (due to a fatal, while exiting)
179
static bool run = false;
180
if(run) {
181
nd_log(NDLS_DAEMON, NDLP_ERR, "EXIT: Recursion detected. Exiting immediately.");
185
- exit(ret);
182
+ exit(1);
183
}
184
run = true;
185
daemon_status_file_update_status(DAEMON_STATUS_EXITING);
@@ -195,13 +192,13 @@ static void netdata_cleanup_and_exit(EXIT_REASON reason) {
192
watcher_shutdown_begin();
193
194
#ifdef ENABLE_DBENGINE
198
- if(!ret && dbengine_enabled)
195
+ if(!abnormal && dbengine_enabled)
196
// flush all dirty pages asap
197
rrdeng_flush_everything_and_wait(false, false, true);
198
#endif
199
200
// notify we are exiting
204
- //analytics_statistic_t statistic = (analytics_statistic_t) {"EXIT", ret?"ERROR":"OK","-"};
201
+ //analytics_statistic_t statistic = (analytics_statistic_t) {"EXIT", abnormal?"ERROR":"OK","-"};
202
//analytics_statistic_send(&statistic);
203
204
netdata_main_spawn_server_cleanup();
@@ -226,7 +223,7 @@ static void netdata_cleanup_and_exit(EXIT_REASON reason) {
223
watcher_step_complete(WATCHER_STEP_ID_STOP_COLLECTORS_AND_STREAMING_THREADS);
224
225
#ifdef ENABLE_DBENGINE
229
- if(!ret && dbengine_enabled)
226
+ if(!abnormal && dbengine_enabled)
227
// flush all dirty pages now that all collectors and streaming completed
228
rrdeng_flush_everything_and_wait(false, false, true);
229
#endif
@@ -256,8 +253,7 @@ static void netdata_cleanup_and_exit(EXIT_REASON reason) {
253
metadata_sync_shutdown_background();
254
watcher_step_complete(WATCHER_STEP_ID_PREPARE_METASYNC_SHUTDOWN);
255
259
- if (ret)
260
- {
256
+ if (abnormal) {
257
watcher_step_complete(WATCHER_STEP_ID_STOP_COLLECTION_FOR_ALL_HOSTS);
258
watcher_step_complete(WATCHER_STEP_ID_WAIT_FOR_DBENGINE_COLLECTORS_TO_FINISH);
259
watcher_step_complete(WATCHER_STEP_ID_STOP_DBENGINE_TIERS);
@@ -304,8 +300,9 @@ static void netdata_cleanup_and_exit(EXIT_REASON reason) {
300
}
301
302
// Don't register a shutdown event if we crashed
307
- if (!ret)
303
+ if (!abnormal)
304
add_agent_event(EVENT_AGENT_SHUTDOWN_TIME, (int64_t)(now_monotonic_usec() - shutdown_start_time));
305
+
306
sqlite_close_databases();
307
watcher_step_complete(WATCHER_STEP_ID_CLOSE_SQL_DATABASES);
308
sqlite_library_shutdown();
@@ -376,28 +373,30 @@ static void netdata_cleanup_and_exit(EXIT_REASON reason) {
373
#endif
374
375
#ifdef ENABLE_SENTRY
379
- if(ret)
376
+ if(abnormal)
377
shutdown_on_fatal();
378
379
nd_sentry_fini();
380
curl_global_cleanup();
384
- exit(ret);
381
+ exit(abnormal ? 1 : 0);
382
#else
386
- if(ret)
387
- _exit(ret);
383
+ if(abnormal)
384
+ _exit(1);
385
else {
386
curl_global_cleanup();
390
- exit(ret);
387
+ exit(0);
388
}
389
#endif
390
}
391
395
-void netdata_cleanup_and_exit_gracefully(EXIT_REASON reason) {
392
+void netdata_exit_gracefully(EXIT_REASON reason) {
393
exit_initiated_add(reason);
394
FUNCTION_RUN_ONCE();
398
- netdata_cleanup_and_exit(reason);
395
+ netdata_cleanup_and_exit(reason, false);
396
}
397
401
-void netdata_cleanup_and_exit_fatal(EXIT_REASON reason) {
402
- netdata_cleanup_and_exit(reason);
398
+// the final callback for the fatal() function
399
+void netdata_exit_fatal(void) {
400
+ netdata_cleanup_and_exit(EXIT_REASON_FATAL, true);
401
+ exit(1);
402
}
src/daemon/daemon-shutdown.h
+8
-2
@@ -10,7 +10,13 @@ void cancel_main_threads(void);
10
void abort_on_fatal_disable(void);
11
void abort_on_fatal_enable(void);
12
13
-void netdata_cleanup_and_exit_gracefully(EXIT_REASON reason);
14
-void netdata_cleanup_and_exit_fatal(EXIT_REASON reason);
13
+#if !defined(OS_WINDOWS)
14
+#define ND_EXIT_NORETURN NORETURN
15
+#else
16
+#define ND_EXIT_NORETURN
17
+#endif
18
+
19
+void netdata_exit_gracefully(EXIT_REASON reason);
20
+void netdata_exit_fatal(void);
21
22
#endif //NETDATA_DAEMON_SHUTDOWN_H
src/daemon/daemon-systemd-watcher.c
+1
-1
@@ -28,7 +28,7 @@ static int shutdown_event_handler(sd_bus_message *m, void *userdata __maybe_unus
28
shutdown ? "true" : "false");
29
30
if(shutdown)
31
- netdata_cleanup_and_exit_gracefully(EXIT_REASON_SYSTEM_SHUTDOWN);
31
+ netdata_exit_gracefully(EXIT_REASON_SYSTEM_SHUTDOWN);
32
33
return 0;
34
}
src/daemon/main.c
+2
-7
@@ -239,11 +239,6 @@ int unittest_prepare_rrd(const char **user) {
239
return 0;
240
}
241
242
-static void fatal_cleanup_and_exit_cb(void) {
243
- netdata_cleanup_and_exit_fatal(EXIT_REASON_FATAL);
244
- exit(1);
245
-}
246
-
242
static void fatal_status_file_save(void) {
243
daemon_status_file_update_status(DAEMON_STATUS_NONE);
244
exit(1);
@@ -780,7 +775,7 @@ int netdata_main(int argc, char **argv) {
775
// this MUST be before anything else - to load the old status file before saving a new one
776
777
daemon_status_file_init(); // this loads the old file
783
- nd_log_register_fatal_data_cb(daemon_status_file_register_fatal);
778
+ nd_log_register_fatal_hook_cb(daemon_status_file_register_fatal);
779
nd_log_register_fatal_final_cb(fatal_status_file_save);
780
exit_initiated_init();
781
@@ -1141,7 +1136,7 @@ int netdata_main(int argc, char **argv) {
1136
// ----------------------------------------------------------------------------------------------------------------
1137
delta_startup_time("done");
1138
1144
- nd_log_register_fatal_final_cb(fatal_cleanup_and_exit_cb);
1139
+ nd_log_register_fatal_final_cb(netdata_exit_fatal);
1140
daemon_status_file_startup_step(NULL);
1141
daemon_status_file_update_status(DAEMON_STATUS_RUNNING);
1142
return 10;
src/daemon/signal-handler.c
+1
-2
@@ -237,8 +237,7 @@ static void process_triggered_signals(void) {
237
nd_log_limits_unlimited();
238
netdata_log_info("SIGNAL: Received %s. Cleaning up to exit...", name);
239
commands_exit();
240
- netdata_cleanup_and_exit_gracefully(signals_waiting[i].reason);
241
- exit(0);
240
+ netdata_exit_gracefully(signals_waiting[i].reason);
241
break;
242
243
case NETDATA_SIGNAL_DEADLY:
src/daemon/winsvc.cc
+1
-1
@@ -109,7 +109,7 @@ static void *call_netdata_cleanup(void *arg)
109
reason = EXIT_REASON_SERVICE_STOP;
110
break;
111
}
112
- netdata_cleanup_and_exit_gracefully(reason);
112
+ netdata_exit_gracefully(reason);
113
114
// Close event handle
115
netdata_service_log("Closing stop event handle...");
src/libnetdata/log/nd_log-init.c
+1
-1
@@ -285,7 +285,7 @@ int nd_log_systemd_journal_fd(void) {
285
286
void nd_log_reopen_log_files_for_spawn_server(const char *name) {
287
nd_log_forked = true;
288
- nd_log.fatal_data_cb = NULL;
288
+ nd_log.fatal_hook_cb = NULL;
289
nd_log.fatal_final_cb = NULL;
290
291
gettid_uncached();
src/libnetdata/log/nd_log-internals.h
+1
-1
@@ -125,7 +125,7 @@ struct nd_log {
125
nd_uuid_t invocation_id;
126
127
ND_LOG_SOURCES overwrite_process_source;
128
- log_event_t fatal_data_cb;
128
+ log_event_t fatal_hook_cb;
129
fatal_event_t fatal_final_cb;
130
131
struct nd_log_source sources[_NDLS_MAX];
src/libnetdata/log/nd_log.c
+10
-11
@@ -110,15 +110,15 @@ static ND_LOG_METHOD nd_logger_select_output(ND_LOG_SOURCES source, FILE **fpp,
110
111
// --------------------------------------------------------------------------------------------------------------------
112
113
-static __thread bool nd_log_event_this = false;
113
+static __thread bool nd_log_fatal_event = false;
114
115
-static void nd_log_event(struct log_field *fields, size_t fields_max __maybe_unused) {
116
- if(!nd_log_event_this)
115
+static void nd_log_fatal_hook(struct log_field *fields, size_t fields_max __maybe_unused) {
116
+ if(!nd_log_fatal_event)
117
return;
118
119
- nd_log_event_this = false;
119
+ nd_log_fatal_event = false;
120
121
- if(!nd_log.fatal_data_cb)
121
+ if(!nd_log.fatal_hook_cb)
122
return;
123
124
const char *filename = log_field_strdupz(&fields[NDF_FILE]);
@@ -128,11 +128,11 @@ static void nd_log_event(struct log_field *fields, size_t fields_max __maybe_unu
128
const char *errno_str = log_field_strdupz(&fields[NDF_ERRNO]);
129
long line = log_field_to_int64(&fields[NDF_LINE]);
130
131
- nd_log.fatal_data_cb(filename, function, message, errno_str, stack_trace, line);
131
+ nd_log.fatal_hook_cb(filename, function, message, errno_str, stack_trace, line);
132
}
133
134
-void nd_log_register_fatal_data_cb(log_event_t cb) {
135
- nd_log.fatal_data_cb = cb;
134
+void nd_log_register_fatal_hook_cb(log_event_t cb) {
135
+ nd_log.fatal_hook_cb = cb;
136
}
137
138
// --------------------------------------------------------------------------------------------------------------------
@@ -147,8 +147,7 @@ void nd_log_register_fatal_final_cb(fatal_event_t cb) {
147
static void nd_logger_log_fields(SPINLOCK *spinlock, FILE *fp, bool limit, ND_LOG_FIELD_PRIORITY priority,
148
ND_LOG_METHOD output, struct nd_log_source *source,
149
struct log_field *fields, size_t fields_max) {
150
-
151
- nd_log_event(fields, fields_max);
150
+ nd_log_fatal_hook(fields, fields_max);
151
152
if(spinlock)
153
spinlock_lock(spinlock);
@@ -488,7 +487,7 @@ void netdata_logger_fatal(const char *file, const char *function, const unsigned
487
}
488
489
// send this event to deamon_status_file
491
- nd_log_event_this = true;
490
+ nd_log_fatal_event = true;
491
492
int saved_errno = errno;
493
size_t saved_winerror = 0;
src/libnetdata/log/nd_log.h
+1
-1
@@ -41,7 +41,7 @@ bool capture_stack_trace_is_async_signal_safe(void);
41
const char *capture_stack_trace_backend(void);
42
43
typedef void (*log_event_t)(const char *filename, const char *function, const char *message, const char *errno_str, const char *stack_trace, long line);
44
-void nd_log_register_fatal_data_cb(log_event_t cb);
44
+void nd_log_register_fatal_hook_cb(log_event_t cb);
45
46
typedef void (*fatal_event_t)(void);
47
void nd_log_register_fatal_final_cb(fatal_event_t cb);
src/web/server/web_client.c
+1
-1
@@ -1191,7 +1191,7 @@ static inline int web_client_process_url(RRDHOST *host, struct web_client *w, ch
1191
buffer_strcat(w->response.data, "I am doing it already");
1192
1193
netdata_log_error("web request to exit received.");
1194
- netdata_cleanup_and_exit_gracefully(EXIT_REASON_API_QUIT);
1194
+ netdata_exit_gracefully(EXIT_REASON_API_QUIT);
1195
return HTTP_RESP_OK;
1196
}
1197
else if(unlikely(hash == hash_debug && strcmp(tok, "debug") == 0)) {