Fix memory-safety and correctness bugs surfaced by Coverity audit (part 8) (#22293)
daemon: free removed stale nodes outside rrd lock Coverity CID 442107 (SLEEP): remove-stale-node held the global RRD write lock while freeing a host. Unlink the host under the lock, then run teardown/freeing outside the lock so logging and stream shutdown waits do not block global RRD progress.
Costa Tsaousis committed
Apr 27, 2026 at 20:24 UTC
8e49531c6f3d7b4eee6be62c89dc245573104e5a
3 files changed
+23
-15
src/daemon/commands.c
+1
-3
@@ -389,9 +389,7 @@ static int remove_ephemeral_host(BUFFER *wb, RRDHOST *host, bool report_error, b
389
host->node_id = UUID_ZERO;
390
buffer_sprintf(wb, "Node '%s' (machine guid: %s) has been unregistered",
391
rrdhost_hostname(host), host->machine_guid);
392
- rrd_wrlock();
393
- rrdhost_free___while_having_rrd_wrlock(host);
394
- rrd_wrunlock();
392
+ rrdhost_free___without_having_rrd_wrlock(host);
393
return 1;
394
}
395
src/database/rrdhost.c
+21
-12
@@ -800,23 +800,15 @@ void rrdhost_cleanup_data_collection_and_health(RRDHOST *host) {
800
rrdhost_hostname(host));
801
}
802
803
-void rrdhost_free___while_having_rrd_wrlock(RRDHOST *host) {
804
- if(!host) return;
805
-
806
- nd_log(NDLS_DAEMON, NDLP_DEBUG,
807
- "RRD: 'host:%s' freeing memory...",
808
- rrdhost_hostname(host));
809
-
810
- // ------------------------------------------------------------------------
811
- // first remove it from the indexes, so that it will not be discoverable
812
-
803
+static void rrdhost_unlink___while_having_rrd_wrlock(RRDHOST *host) {
804
+ // Remove it from the indexes first, so blocking teardown cannot rediscover it.
805
rrdhost_index_del_by_guid(host);
806
807
if (host->prev)
808
DOUBLE_LINKED_LIST_REMOVE_ITEM_UNSAFE(localhost, host, prev, next);
809
+}
810
818
- // ------------------------------------------------------------------------
819
-
811
+static void rrdhost_free_unlinked(RRDHOST *host) {
812
rrdhost_cleanup_data_collection_and_health(host);
813
814
// ------------------------------------------------------------------------
@@ -847,6 +839,23 @@ void rrdhost_free___while_having_rrd_wrlock(RRDHOST *host) {
839
freez(host);
840
}
841
842
+void rrdhost_free___while_having_rrd_wrlock(RRDHOST *host) {
843
+ if(!host) return;
844
+
845
+ rrdhost_unlink___while_having_rrd_wrlock(host);
846
+ rrdhost_free_unlinked(host);
847
+}
848
+
849
+void rrdhost_free___without_having_rrd_wrlock(RRDHOST *host) {
850
+ if(!host) return;
851
+
852
+ rrd_wrlock();
853
+ rrdhost_unlink___while_having_rrd_wrlock(host);
854
+ rrd_wrunlock();
855
+
856
+ rrdhost_free_unlinked(host);
857
+}
858
+
859
void rrdhost_free_all(void) {
860
rrd_wrlock();
861
src/database/rrdhost.h
+1
@@ -456,6 +456,7 @@ RRDHOST *rrdhost_find_or_create(
456
void rrdhost_free_all(void);
457
458
void rrdhost_free___while_having_rrd_wrlock(RRDHOST *host);
459
+void rrdhost_free___without_having_rrd_wrlock(RRDHOST *host);
460
void rrdhost_cleanup_data_collection_and_health(RRDHOST *host);
461
462
bool rrdhost_should_be_cleaned_up(RRDHOST *host, RRDHOST *protected_host, time_t now_s);