@cryptotaxi247 / netdata-1 / commits / 5c96c3e2a

Fix shutdown race when restoring alert information from the database (#22448)

* fix(health): close shutdown race in sql_health_alarm_log_load Shutdown does not actively wait for HEALTH to leave sqlite3_step: service_wait_exit(SERVICE_HEALTH) is bounded to 3s, cancel_main_threads only joins threads already marked EXITED, and nd_thread_join_threads reaps the exited list rather than blocking on live threads. If HEALTH is still iterating SQL_LOAD_HEALTH_LOG when sqlite_close_databases() runs, sqlite3_close_v2() tears down the page cache underneath it and the next pcache1Unpin faults at offset 0x30. Bail the row loop on !service_running(SERVICE_HEALTH), matching the existing pattern at sqlite_health.c:567. Also move rw_spinlock_init() before sql_health_alarm_log_load() so the lock the load already takes is initialized first. * fix(health): change spinlock to write lock for health log access

Stelios Fragkakis committed May 9, 2026 at 16:46 UTC 5c96c3e2a724f09774e286e946778c05fcf1c190
2 files changed +4 -4
src/database/sqlite/sqlite_health.c
+3 -3
@@ -674,9 +674,9 @@ void sql_health_alarm_log_load(RRDHOST *host)
674 foreach_rrdcalc_in_rrdhost_done(rc);
675
676 param = 0;
677 - rw_spinlock_read_lock(&host->health_log.spinlock);
677 + rw_spinlock_write_lock(&host->health_log.spinlock);
678
679 - while (sqlite3_step_monitored(res) == SQLITE_ROW) {
679 + while (service_running(SERVICE_HEALTH) && sqlite3_step_monitored(res) == SQLITE_ROW) {
680 ALARM_ENTRY *ae = NULL;
681
682 // check that we have valid ids
@@ -806,7 +806,7 @@ void sql_health_alarm_log_load(RRDHOST *host)
806 loaded++;
807 }
808
809 - rw_spinlock_read_unlock(&host->health_log.spinlock);
809 + rw_spinlock_write_unlock(&host->health_log.spinlock);
810
811 dictionary_destroy(all_rrdcalcs);
812 all_rrdcalcs = NULL;
src/health/health_event_loop.c
+1 -1
@@ -244,8 +244,8 @@ static void health_initialize_rrdhost(RRDHOST *host) {
244 host->health_log.next_log_id = get_uint32_id();
245 host->health_log.next_alarm_id = 0;
246
247 - sql_health_alarm_log_load(host);
247 rw_spinlock_init(&host->health_log.spinlock);
248 + sql_health_alarm_log_load(host);
249 rrdhost_flag_set(host, RRDHOST_FLAG_INITIALIZED_HEALTH);
250
251