@cryptotaxi247 / netdata-1 / commits / a4951c1b7

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)) {