Fix ebpf shutdown and cgroup ipc integration (#22242)
fix: ensure proper cleanup and synchronization in cgroup and ebpf integration
Stelios Fragkakis committed
Apr 22, 2026 at 09:20 UTC
1e81d422cfb750a88e06a88d55b14cb1cba6ca12
4 files changed
+18
-10
src/collectors/cgroups.plugin/cgroup-discovery.c
+3
-1
@@ -1194,6 +1194,9 @@ void cgroup_discovery_worker(void *ptr)
1194
discovery_find_all_cgroups();
1195
}
1196
1197
+ // Stop the netipc server first so its worker threads cannot iterate cgroup_root while we free it.
1198
+ cgroup_netipc_cleanup();
1199
+
1200
// free all cgroups
1201
netdata_mutex_lock(&cgroup_root_mutex);
1202
while(cgroup_root) {
@@ -1204,7 +1207,6 @@ void cgroup_discovery_worker(void *ptr)
1207
netdata_mutex_unlock(&cgroup_root_mutex);
1208
1209
collector_info("discovery thread stopped");
1207
- cgroup_netipc_cleanup();
1210
worker_unregister();
1211
service_exits();
1212
__atomic_store_n(&discovery_thread.exited, 1, __ATOMIC_RELEASE);
src/collectors/cgroups.plugin/cgroup-netipc.c
-4
@@ -90,13 +90,9 @@ static bool cgroups_snapshot_handler(void *user __maybe_unused,
90
}
91
}
92
93
- netdata_mutex_unlock(&cgroup_root_mutex);
94
-
93
bool log_zero_generation = false;
94
bool log_truncated_generation = false;
95
98
- netdata_mutex_lock(&cgroup_root_mutex);
99
-
96
if (count == 0 && last_logged_zero_generation != snapshot_generation) {
97
last_logged_zero_generation = snapshot_generation;
98
log_zero_generation = true;
src/collectors/ebpf.plugin/ebpf.c
+6
@@ -1158,6 +1158,12 @@ void ebpf_stop_threads(int sig)
1158
#endif
1159
netdata_mutex_unlock(&mutex_cgroup_shm);
1160
1161
+ // Join the cgroup integration thread before ebpf_exit() tears down the netipc cache it reads.
1162
+ if (cgroup_integration_thread.thread) {
1163
+ nd_thread_join(cgroup_integration_thread.thread);
1164
+ cgroup_integration_thread.thread = NULL;
1165
+ }
1166
+
1167
usec_t before_checks_ut = now_monotonic_usec();
1168
if (!ebpf_pre_exit_check_done) {
1169
ebpf_check_before2go();
src/collectors/ebpf.plugin/ebpf_cgroup.c
+9
-5
@@ -347,11 +347,8 @@ static void ebpf_parse_cgroup_netipc_data(void)
347
uint64_t generation = ebpf_cgroup_cache.generation;
348
uint32_t enabled_count = 0;
349
350
- // Publish the latest cgroup state before collectors read the lock-free flags.
350
int systemd_enabled = (int)ebpf_cgroup_cache.systemd_enabled;
351
int integration_active = (count > 0) ? 1 : 0;
353
- ebpf_cgroup_systemd_enabled_set(systemd_enabled);
354
- ebpf_cgroup_integration_active_set(integration_active);
352
353
for (uint32_t i = 0; i < count; i++) {
354
const nipc_cgroups_cache_item_t *item = &ebpf_cgroup_cache.items[i];
@@ -371,6 +368,10 @@ static void ebpf_parse_cgroup_netipc_data(void)
368
netdata_mutex_lock(&mutex_cgroup_shm);
369
preserved_targets = ebpf_count_cgroup_targets_unsafe();
370
preserved_pids = ebpf_count_cgroup_pids_unsafe();
371
+ // Publish flags while holding the mutex so collectors never observe a flag
372
+ // change before the pid/target lists match it.
373
+ ebpf_cgroup_systemd_enabled_set(systemd_enabled);
374
+ ebpf_cgroup_integration_active_set(integration_active);
375
netdata_mutex_unlock(&mutex_cgroup_shm);
376
377
if (last_count != 0 ||
@@ -416,6 +417,10 @@ static void ebpf_parse_cgroup_netipc_data(void)
417
int chart_refresh_needed = previous_count != count;
418
ebpf_send_cgroup_chart_set(chart_refresh_needed);
419
previous_count = count;
420
+ // Publish integration flags only after the target/pid lists have been rebuilt,
421
+ // so collectors never observe integration_active=1 with stale pid state.
422
+ ebpf_cgroup_systemd_enabled_set(systemd_enabled);
423
+ ebpf_cgroup_integration_active_set(integration_active);
424
netdata_mutex_unlock(&mutex_cgroup_shm);
425
426
if (last_count != count ||
@@ -423,8 +428,7 @@ static void ebpf_parse_cgroup_netipc_data(void)
428
previous_imported_targets != imported_targets ||
429
previous_total_pids != total_pids ||
430
previous_integration_active != integration_active ||
426
- previous_systemd_enabled != systemd_enabled ||
427
- enabled_count == 0 || imported_targets == 0 || total_pids == 0) {
431
+ previous_systemd_enabled != systemd_enabled) {
432
collector_info(
433
"EBPF CGROUP: netipc snapshot generation=%llu items=%u enabled=%u imported_targets=%zu total_pids=%zu "
434
"send_cgroup_chart=%d integration_active=%d systemd_enabled=%d refresh_failures=%d",