@cryptotaxi247 / netdata-1 / commits / 87dbbaadb

do not recurse cleanup on shutdown (#19894)

* do not recurse cleanup on shutdown * make exit_initiated sigatomic_t and hide it behind a function * fix freebsd and windows

Costa Tsaousis committed Mar 17, 2025 at 23:48 UTC 87dbbaadb625edb5d05c3605f7dd02fc0a18237c
20 files changed +54 -44
src/collectors/cups.plugin/cups_plugin.c
+3 -3
@@ -243,7 +243,7 @@ int main(int argc, char **argv) {
243 for (iteration = 0; 1; iteration++) {
244 heartbeat_next(&hb);
245
246 - if (unlikely(exit_initiated))
246 + if (unlikely(exit_initiated_get()))
247 break;
248
249 reset_metrics();
@@ -315,7 +315,7 @@ int main(int argc, char **argv) {
315 }
316 cupsFreeDests(num_dest_total, dests);
317
318 - if (unlikely(exit_initiated))
318 + if (unlikely(exit_initiated_get()))
319 break;
320
321 cups_job_t *jobs, *curr_job;
@@ -410,7 +410,7 @@ int main(int argc, char **argv) {
410
411 fflush(stdout);
412
413 - if (unlikely(exit_initiated))
413 + if (unlikely(exit_initiated_get()))
414 break;
415
416 // restart check (14400 seconds)
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(EXIT_REASON_FATAL, NULL, NULL, NULL);
94 + netdata_cleanup_and_exit_fatal(EXIT_REASON_FATAL);
95
96 // check the enabled status for each module
97 int i;
src/collectors/nfacct.plugin/plugin_nfacct.c
+1 -1
@@ -837,7 +837,7 @@ int main(int argc, char **argv) {
837 for(iteration = 0; 1; iteration++) {
838 usec_t dt = heartbeat_next(&hb);
839
840 - if(unlikely(exit_initiated)) break;
840 + if(unlikely(exit_initiated_get())) break;
841
842 if(debug && iteration)
843 fprintf(stderr, "nfacct.plugin: iteration %zu, dt %"PRIu64" usec\n"
src/collectors/perf.plugin/perf_plugin.c
+1 -1
@@ -1325,7 +1325,7 @@ int main(int argc, char **argv) {
1325 for(iteration = 0; 1; iteration++) {
1326 usec_t dt = heartbeat_next(&hb);
1327
1328 - if (unlikely(exit_initiated))
1328 + if (unlikely(exit_initiated_get()))
1329 break;
1330
1331 if (unlikely(debug && iteration))
src/collectors/xenstat.plugin/xenstat_plugin.c
+1 -1
@@ -1026,7 +1026,7 @@ int main(int argc, char **argv) {
1026 for(iteration = 0; 1; iteration++) {
1027 usec_t dt = heartbeat_next(&hb);
1028
1029 - if(unlikely(exit_initiated)) break;
1029 + if(unlikely(exit_initiated_get())) break;
1030
1031 if(unlikely(debug && iteration))
1032 fprintf(stderr, "xenstat.plugin: iteration %zu, dt %lu usec\n", iteration, dt);
src/daemon/commands.c
+1 -1
@@ -164,7 +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(EXIT_REASON_CMD_EXIT, NULL, NULL, NULL);
167 + netdata_cleanup_and_exit_gracefully(EXIT_REASON_CMD_EXIT);
168 exit(0);
169
170 return CMD_STATUS_SUCCESS;
src/daemon/daemon-service.c
+1 -1
@@ -90,7 +90,7 @@ bool service_running(SERVICE_TYPE service) {
90 if (sth->type == SERVICE_THREAD_TYPE_NETDATA)
91 cancelled = nd_thread_signaled_to_cancel();
92
93 - return !sth->stop_immediately && !exit_initiated && !cancelled;
93 + return !sth->stop_immediately && !exit_initiated_get() && !cancelled;
94 }
95
96 void service_signal_exit(SERVICE_TYPE service) {
src/daemon/daemon-shutdown.c
+20 -12
@@ -38,7 +38,7 @@ extern struct netdata_static_thread *static_threads;
38
39 void netdata_log_exit_reason(void) {
40 CLEAN_BUFFER *wb = buffer_create(0, NULL);
41 - EXIT_REASON_2buffer(wb, exit_initiated, ", ");
41 + EXIT_REASON_2buffer(wb, exit_initiated_get(), ", ");
42
43 ND_LOG_STACK lgs[] = {
44 ND_LOG_FIELD_UUID(NDF_MESSAGE_ID, &netdata_exit_msgid),
@@ -46,7 +46,7 @@ void netdata_log_exit_reason(void) {
46 };
47 ND_LOG_STACK_PUSH(lgs);
48
49 - nd_log(NDLS_DAEMON, is_exit_reason_normal(exit_initiated) ? NDLP_NOTICE : NDLP_CRIT,
49 + nd_log(NDLS_DAEMON, is_exit_reason_normal(exit_initiated_get()) ? NDLP_NOTICE : NDLP_CRIT,
50 "NETDATA SHUTDOWN: initializing shutdown with code due to: %s",
51 buffer_tostring(wb));
52 }
@@ -109,8 +109,7 @@ static void *rrdeng_exit_background(void *ptr) {
109 }
110
111 #ifdef ENABLE_DBENGINE
112 -static void rrdeng_flush_everything_and_wait(bool wait_flush, bool wait_collectors, bool dirty_only)
113 -{
112 +static void rrdeng_flush_everything_and_wait(bool wait_flush, bool wait_collectors, bool dirty_only) {
113 static size_t starting_size_to_flush = 0;
114
115 if(!pgc_hot_and_dirty_entries(main_cache))
@@ -172,9 +171,12 @@ static void rrdeng_flush_everything_and_wait(bool wait_flush, bool wait_collecto
171 }
172 #endif
173
175 -void netdata_cleanup_and_exit(EXIT_REASON reason, const char *action, const char *action_result, const char *action_data) {
174 +#if !defined(OS_WINDOWS)
175 +NORETURN
176 +#endif
177 +static void netdata_cleanup_and_exit(EXIT_REASON reason) {
178 exit_initiated_set(reason);
177 - int ret = is_exit_reason_normal(exit_initiated) ? 0 : 1;
179 + int ret = is_exit_reason_normal(exit_initiated_get()) ? 0 : 1;
180
181 // don't recurse (due to a fatal, while exiting)
182 static bool run = false;
@@ -198,13 +200,9 @@ void netdata_cleanup_and_exit(EXIT_REASON reason, const char *action, const char
200 rrdeng_flush_everything_and_wait(false, false, true);
201 #endif
202
201 - // send the stat from our caller
202 - analytics_statistic_t statistic = { action, action_result, action_data };
203 - analytics_statistic_send(&statistic);
204 -
203 // notify we are exiting
206 - statistic = (analytics_statistic_t) {"EXIT", ret?"ERROR":"OK","-"};
207 - analytics_statistic_send(&statistic);
204 + //analytics_statistic_t statistic = (analytics_statistic_t) {"EXIT", ret?"ERROR":"OK","-"};
205 + //analytics_statistic_send(&statistic);
206
207 netdata_main_spawn_server_cleanup();
208 watcher_step_complete(WATCHER_STEP_ID_DESTROY_MAIN_SPAWN_SERVER);
@@ -393,3 +391,13 @@ void netdata_cleanup_and_exit(EXIT_REASON reason, const char *action, const char
391 }
392 #endif
393 }
394 +
395 +void netdata_cleanup_and_exit_gracefully(EXIT_REASON reason) {
396 + exit_initiated_add(reason);
397 + FUNCTION_RUN_ONCE();
398 + netdata_cleanup_and_exit(reason);
399 +}
400 +
401 +void netdata_cleanup_and_exit_fatal(EXIT_REASON reason) {
402 + netdata_cleanup_and_exit(reason);
403 +}
src/daemon/daemon-shutdown.h
+2 -5
@@ -10,10 +10,7 @@ void cancel_main_threads(void);
10 void abort_on_fatal_disable(void);
11 void abort_on_fatal_enable(void);
12
13 -#ifdef OS_WINDOWS
14 -void netdata_cleanup_and_exit(EXIT_REASON reason, const char *action, const char *action_result, const char *action_data);
15 -#else
16 -void netdata_cleanup_and_exit(EXIT_REASON reason, const char *action, const char *action_result, const char *action_data) NORETURN;
17 -#endif
13 +void netdata_cleanup_and_exit_gracefully(EXIT_REASON reason);
14 +void netdata_cleanup_and_exit_fatal(EXIT_REASON reason);
15
16 #endif //NETDATA_DAEMON_SHUTDOWN_H
src/daemon/daemon-status-file.c
+1 -1
@@ -614,7 +614,7 @@ static void daemon_status_file_refresh(DAEMON_STATUS status) {
614
615 get_daemon_status_fields_from_system_info(&session_status);
616
617 - session_status.exit_reason = exit_initiated;
617 + session_status.exit_reason = exit_initiated_get();
618 session_status.profile = nd_profile_detect_and_configure(false);
619
620 if(status != DAEMON_STATUS_NONE)
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(EXIT_REASON_SYSTEM_SHUTDOWN, NULL, NULL, NULL);
31 + netdata_cleanup_and_exit_gracefully(EXIT_REASON_SYSTEM_SHUTDOWN);
32
33 return 0;
34 }
src/daemon/main.c
+1 -1
@@ -240,7 +240,7 @@ int unittest_prepare_rrd(const char **user) {
240 }
241
242 static void fatal_cleanup_and_exit_cb(void) {
243 - netdata_cleanup_and_exit(EXIT_REASON_FATAL, "fatal error", "exiting", NULL);
243 + netdata_cleanup_and_exit_fatal(EXIT_REASON_FATAL);
244 exit(1);
245 }
246
src/daemon/signal-handler.c
+1 -1
@@ -237,7 +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(signals_waiting[i].reason, NULL, NULL, NULL);
240 + netdata_cleanup_and_exit_gracefully(signals_waiting[i].reason);
241 exit(0);
242 break;
243
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(reason, NULL, NULL, NULL);
112 + netdata_cleanup_and_exit_gracefully(reason);
113
114 // Close event handle
115 netdata_service_log("Closing stop event handle...");
src/database/engine/cache.c
+1 -1
@@ -2312,7 +2312,7 @@ bool pgc_flush_pages(PGC *cache) {
2312 }
2313
2314 void pgc_page_hot_set_end_time_s(PGC *cache __maybe_unused, PGC_PAGE *page, time_t end_time_s, size_t additional_bytes) {
2315 - internal_fatal(!is_page_hot(page) && !exit_initiated,
2315 + internal_fatal(!is_page_hot(page) && !exit_initiated_get(),
2316 "DBENGINE CACHE: end_time_s update on non-hot page");
2317
2318 internal_fatal(end_time_s < __atomic_load_n(&page->end_time_s, __ATOMIC_RELAXED),
src/database/engine/page.c
+2 -2
@@ -897,14 +897,14 @@ size_t pgd_append_point(
897 uint32_t expected_slot)
898 {
899 if (pg->states & PGD_STATE_SCHEDULED_FOR_FLUSHING) {
900 - if(exit_initiated == EXIT_REASON_NONE)
900 + if(exit_initiated_get() == EXIT_REASON_NONE)
901 pgd_fatal(pg, "Data collection on page already scheduled for flushing");
902 else
903 return 0;
904 }
905
906 if (!(pg->states & PGD_STATE_CREATED_FROM_COLLECTOR)) {
907 - if(exit_initiated == EXIT_REASON_NONE)
907 + if(exit_initiated_get() == EXIT_REASON_NONE)
908 pgd_fatal(pg, "DBENGINE: collection on page not created from a collector");
909 else
910 return 0;
src/health/rrdcalc.c
+1 -1
@@ -250,7 +250,7 @@ static void rrdcalc_link_to_rrdset(RRDCALC *rc) {
250 static void rrdcalc_unlink_from_rrdset(RRDCALC *rc, bool having_ll_wrlock) {
251 RRDSET *st = rc->rrdset;
252
253 - if (!exit_initiated) {
253 + if (!exit_initiated_get()) {
254 RRDHOST *host = st->rrdhost;
255
256 time_t now = now_realtime_sec();
src/libnetdata/exit/exit_initiated.c
+11 -5
@@ -2,7 +2,7 @@
2
3 #include "../libnetdata.h"
4
5 -volatile EXIT_REASON exit_initiated = EXIT_REASON_NONE;
5 +static volatile sig_atomic_t exit_initiated = EXIT_REASON_NONE;
6
7 ENUM_STR_MAP_DEFINE(EXIT_REASON) = {
8 { EXIT_REASON_SIGBUS, "signal-bus-error"},
@@ -108,15 +108,22 @@ void exit_initiated_init(void) {
108 self = os_get_file_metadata(self_path);
109 }
110
111 +ALWAYS_INLINE
112 +EXIT_REASON exit_initiated_get(void) {
113 + return (EXIT_REASON)exit_initiated;
114 +}
115 +
116 void exit_initiated_add(EXIT_REASON reason) {
112 - exit_initiated |= reason;
117 + exit_initiated |= (sig_atomic_t)reason;
118 }
119
120 void exit_initiated_set(EXIT_REASON reason) {
116 - if(exit_initiated == EXIT_REASON_NONE && !(reason & EXIT_REASON_SYSTEM_SHUTDOWN) && is_system_shutdown())
121 + EXIT_REASON old = exit_initiated_get();
122 +
123 + if(old == EXIT_REASON_NONE && !(reason & EXIT_REASON_SYSTEM_SHUTDOWN) && is_system_shutdown())
124 reason |= EXIT_REASON_SYSTEM_SHUTDOWN;
125
119 - if(exit_initiated == EXIT_REASON_NONE && self_path && OS_FILE_METADATA_OK(self)) {
126 + if(old == EXIT_REASON_NONE && self_path && OS_FILE_METADATA_OK(self)) {
127 OS_FILE_METADATA self_now = os_get_file_metadata(self_path);
128 if(OS_FILE_METADATA_OK(self_now) && (self_now.modified_time != self.modified_time || self_now.size_bytes != self.size_bytes))
129 reason |= EXIT_REASON_UPDATE;
@@ -127,4 +134,3 @@ void exit_initiated_set(EXIT_REASON reason) {
134 // we will have all of them
135 exit_initiated_add(reason);
136 }
130 -
src/libnetdata/exit/exit_initiated.h
+1 -2
@@ -82,9 +82,8 @@ typedef enum {
82 typedef struct web_buffer BUFFER;
83 BITMAP_STR_DEFINE_FUNCTIONS_EXTERN(EXIT_REASON);
84
85 -extern volatile EXIT_REASON exit_initiated;
86 -
85 void exit_initiated_init(void);
86 +EXIT_REASON exit_initiated_get(void);
87 void exit_initiated_set(EXIT_REASON reason);
88 void exit_initiated_add(EXIT_REASON reason);
89
src/web/server/web_client.c
+2 -2
@@ -1185,13 +1185,13 @@ static inline int web_client_process_url(RRDHOST *host, struct web_client *w, ch
1185 w->response.data->content_type = CT_TEXT_PLAIN;
1186 buffer_flush(w->response.data);
1187
1188 - if(!exit_initiated)
1188 + if(!exit_initiated_get())
1189 buffer_strcat(w->response.data, "ok, will do...");
1190 else
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(EXIT_REASON_API_QUIT, NULL, NULL, NULL);
1194 + netdata_cleanup_and_exit_gracefully(EXIT_REASON_API_QUIT);
1195 return HTTP_RESP_OK;
1196 }
1197 else if(unlikely(hash == hash_debug && strcmp(tok, "debug") == 0)) {