@cryptotaxi247 / netdata-1 / commits / 870acd611

Improve eBPF exit (#14012)

thiagoftsm committed Nov 25, 2022 at 13:59 UTC 870acd61123ece7c074242e1b02d47cb7c667e38
19 files changed +683 -651
collectors/ebpf.plugin/ebpf.c
+70 -36
@@ -27,8 +27,10 @@ struct config collector_config = { .first_section = NULL,
27 int running_on_kernel = 0;
28 int ebpf_nprocs;
29 int isrh = 0;
30 +int main_thread_id = 0;
31
32 pthread_mutex_t lock;
33 +pthread_mutex_t ebpf_exit_cleanup;
34 pthread_mutex_t collect_data_mutex;
35 pthread_cond_t collect_data_cond_var;
36
@@ -41,7 +43,7 @@ ebpf_module_t ebpf_modules[] = {
43 .config_file = NETDATA_PROCESS_CONFIG_FILE,
44 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_10 |
45 NETDATA_V5_14,
44 - .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL},
46 + .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL, .thread = NULL},
47 { .thread_name = "socket", .config_name = "socket", .enabled = 0, .start_routine = ebpf_socket_thread,
48 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
49 .apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
@@ -49,7 +51,7 @@ ebpf_module_t ebpf_modules[] = {
51 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &socket_config,
52 .config_file = NETDATA_NETWORK_CONFIG_FILE,
53 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
52 - .load = EBPF_LOAD_LEGACY, .targets = socket_targets, .probe_links = NULL, .objects = NULL},
54 + .load = EBPF_LOAD_LEGACY, .targets = socket_targets, .probe_links = NULL, .objects = NULL, .thread = NULL},
55 { .thread_name = "cachestat", .config_name = "cachestat", .enabled = 0, .start_routine = ebpf_cachestat_thread,
56 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
57 .apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
@@ -58,7 +60,7 @@ ebpf_module_t ebpf_modules[] = {
60 .config_file = NETDATA_CACHESTAT_CONFIG_FILE,
61 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18|
62 NETDATA_V5_4 | NETDATA_V5_14 | NETDATA_V5_15 | NETDATA_V5_16,
61 - .load = EBPF_LOAD_LEGACY, .targets = cachestat_targets, .probe_links = NULL, .objects = NULL},
63 + .load = EBPF_LOAD_LEGACY, .targets = cachestat_targets, .probe_links = NULL, .objects = NULL, .thread = NULL},
64 { .thread_name = "sync", .config_name = "sync", .enabled = 0, .start_routine = ebpf_sync_thread,
65 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
66 .apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
@@ -66,7 +68,7 @@ ebpf_module_t ebpf_modules[] = {
68 .config_file = NETDATA_SYNC_CONFIG_FILE,
69 // All syscalls have the same kernels
70 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
69 - .load = EBPF_LOAD_LEGACY, .targets = sync_targets, .probe_links = NULL, .objects = NULL},
71 + .load = EBPF_LOAD_LEGACY, .targets = sync_targets, .probe_links = NULL, .objects = NULL, .thread = NULL},
72 { .thread_name = "dc", .config_name = "dc", .enabled = 0, .start_routine = ebpf_dcstat_thread,
73 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
74 .apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
@@ -74,7 +76,7 @@ ebpf_module_t ebpf_modules[] = {
76 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &dcstat_config,
77 .config_file = NETDATA_DIRECTORY_DCSTAT_CONFIG_FILE,
78 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
77 - .load = EBPF_LOAD_LEGACY, .targets = dc_targets, .probe_links = NULL, .objects = NULL},
79 + .load = EBPF_LOAD_LEGACY, .targets = dc_targets, .probe_links = NULL, .objects = NULL, .thread = NULL},
80 { .thread_name = "swap", .config_name = "swap", .enabled = 0, .start_routine = ebpf_swap_thread,
81 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
82 .apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
@@ -82,7 +84,7 @@ ebpf_module_t ebpf_modules[] = {
84 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &swap_config,
85 .config_file = NETDATA_DIRECTORY_SWAP_CONFIG_FILE,
86 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
85 - .load = EBPF_LOAD_LEGACY, .targets = swap_targets, .probe_links = NULL, .objects = NULL},
87 + .load = EBPF_LOAD_LEGACY, .targets = swap_targets, .probe_links = NULL, .objects = NULL, .thread = NULL},
88 { .thread_name = "vfs", .config_name = "vfs", .enabled = 0, .start_routine = ebpf_vfs_thread,
89 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
90 .apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
@@ -90,28 +92,28 @@ ebpf_module_t ebpf_modules[] = {
92 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &vfs_config,
93 .config_file = NETDATA_DIRECTORY_VFS_CONFIG_FILE,
94 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
93 - .load = EBPF_LOAD_LEGACY, .targets = vfs_targets, .probe_links = NULL, .objects = NULL},
95 + .load = EBPF_LOAD_LEGACY, .targets = vfs_targets, .probe_links = NULL, .objects = NULL, .thread = NULL},
96 { .thread_name = "filesystem", .config_name = "filesystem", .enabled = 0, .start_routine = ebpf_filesystem_thread,
97 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
98 .apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
99 .apps_routine = NULL, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &fs_config,
100 .config_file = NETDATA_FILESYSTEM_CONFIG_FILE,
101 //We are setting kernels as zero, because we load eBPF programs according the kernel running.
100 - .kernels = 0, .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL },
102 + .kernels = 0, .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL, .thread = NULL },
103 { .thread_name = "disk", .config_name = "disk", .enabled = 0, .start_routine = ebpf_disk_thread,
104 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
105 .apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
106 .apps_routine = NULL, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &disk_config,
107 .config_file = NETDATA_DISK_CONFIG_FILE,
108 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
107 - .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL},
109 + .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL, .thread = NULL},
110 { .thread_name = "mount", .config_name = "mount", .enabled = 0, .start_routine = ebpf_mount_thread,
111 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
112 .apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
113 .apps_routine = NULL, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &mount_config,
114 .config_file = NETDATA_MOUNT_CONFIG_FILE,
115 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
114 - .load = EBPF_LOAD_LEGACY, .targets = mount_targets, .probe_links = NULL, .objects = NULL},
116 + .load = EBPF_LOAD_LEGACY, .targets = mount_targets, .probe_links = NULL, .objects = NULL, .thread = NULL},
117 { .thread_name = "fd", .config_name = "fd", .enabled = 0, .start_routine = ebpf_fd_thread,
118 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
119 .apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
@@ -120,21 +122,21 @@ ebpf_module_t ebpf_modules[] = {
122 .config_file = NETDATA_FD_CONFIG_FILE,
123 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_11 |
124 NETDATA_V5_14,
123 - .load = EBPF_LOAD_LEGACY, .targets = fd_targets, .probe_links = NULL, .objects = NULL},
125 + .load = EBPF_LOAD_LEGACY, .targets = fd_targets, .probe_links = NULL, .objects = NULL, .thread = NULL},
126 { .thread_name = "hardirq", .config_name = "hardirq", .enabled = 0, .start_routine = ebpf_hardirq_thread,
127 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
128 .apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
129 .apps_routine = NULL, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &hardirq_config,
130 .config_file = NETDATA_HARDIRQ_CONFIG_FILE,
131 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
130 - .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL},
132 + .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL, .thread = NULL},
133 { .thread_name = "softirq", .config_name = "softirq", .enabled = 0, .start_routine = ebpf_softirq_thread,
134 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
135 .apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
136 .apps_routine = NULL, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &softirq_config,
137 .config_file = NETDATA_SOFTIRQ_CONFIG_FILE,
138 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
137 - .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL},
139 + .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL, .thread = NULL},
140 { .thread_name = "oomkill", .config_name = "oomkill", .enabled = 0, .start_routine = ebpf_oomkill_thread,
141 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
142 .apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
@@ -142,7 +144,7 @@ ebpf_module_t ebpf_modules[] = {
144 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &oomkill_config,
145 .config_file = NETDATA_OOMKILL_CONFIG_FILE,
146 .kernels = NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
145 - .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL},
147 + .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL, .thread = NULL},
148 { .thread_name = "shm", .config_name = "shm", .enabled = 0, .start_routine = ebpf_shm_thread,
149 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
150 .apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
@@ -150,19 +152,19 @@ ebpf_module_t ebpf_modules[] = {
152 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &shm_config,
153 .config_file = NETDATA_DIRECTORY_SHM_CONFIG_FILE,
154 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
153 - .load = EBPF_LOAD_LEGACY, .targets = shm_targets, .probe_links = NULL, .objects = NULL},
155 + .load = EBPF_LOAD_LEGACY, .targets = shm_targets, .probe_links = NULL, .objects = NULL, .thread = NULL},
156 { .thread_name = "mdflush", .config_name = "mdflush", .enabled = 0, .start_routine = ebpf_mdflush_thread,
157 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
158 .apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
159 .apps_routine = NULL, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &mdflush_config,
160 .config_file = NETDATA_DIRECTORY_MDFLUSH_CONFIG_FILE,
161 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
160 - .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL},
162 + .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL, .thread = NULL},
163 { .thread_name = NULL, .enabled = 0, .start_routine = NULL, .update_every = EBPF_DEFAULT_UPDATE_EVERY,
164 .global_charts = 0, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO, .apps_level = NETDATA_APPS_NOT_SET,
165 .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL,
166 .pid_map_size = 0, .names = NULL, .cfg = NULL, .config_name = NULL, .kernels = 0, .load = EBPF_LOAD_LEGACY,
165 - .targets = NULL, .probe_links = NULL, .objects = NULL},
167 + .targets = NULL, .probe_links = NULL, .objects = NULL, .thread = NULL},
168 };
169
170 struct netdata_static_thread ebpf_threads[] = {
@@ -432,6 +434,7 @@ ebpf_sync_syscalls_t local_syscalls[] = {
434 }
435 };
436
437 +
438 // Link with apps.plugin
439 ebpf_process_stat_t *global_process_stat = NULL;
440
@@ -463,16 +466,16 @@ char *btf_path = NULL;
466
467 /**
468 * Close the collector gracefully
466 - *
467 - * @param sig is the signal number used to close the collector
469 */
469 -static void ebpf_exit(int sig)
470 +static void ebpf_exit()
471 {
472 #ifdef LIBBPF_MAJOR_VERSION
473 + pthread_mutex_lock(&ebpf_exit_cleanup);
474 if (default_btf) {
475 btf__free(default_btf);
476 default_btf = NULL;
477 }
478 + pthread_mutex_unlock(&ebpf_exit_cleanup);
479 #endif
480
481 char filename[FILENAME_MAX + 1];
@@ -480,7 +483,7 @@ static void ebpf_exit(int sig)
483 if (unlink(filename))
484 error("Cannot remove PID file %s", filename);
485
483 - exit(sig);
486 + exit(0);
487 }
488
489 /**
@@ -513,44 +516,66 @@ int ebpf_exit_plugin = 0;
516 */
517 static void ebpf_stop_threads(int sig)
518 {
516 - ebpf_exit_plugin = 1;
519 + UNUSED(sig);
520 + static int only_one = 0;
521 +
522 int i;
518 - for (i = 0; ebpf_threads[i].name != NULL; i++);
523 + // Child thread should be closed by itself.
524 + pthread_mutex_lock(&ebpf_exit_cleanup);
525 + if (main_thread_id != gettid() || only_one) {
526 + pthread_mutex_unlock(&ebpf_exit_cleanup);
527 + return;
528 + }
529 + only_one = 1;
530 + for (i = 0; ebpf_threads[i].name != NULL; i++) {
531 + if (ebpf_threads[i].enabled != NETDATA_THREAD_EBPF_STOPPED)
532 + netdata_thread_cancel(*ebpf_threads[i].thread);
533 + }
534 + pthread_mutex_unlock(&ebpf_exit_cleanup);
535
520 - usec_t max = 2 * USEC_PER_SEC, step = 100000;
536 + ebpf_exit_plugin = 1;
537 + usec_t max = 3 * USEC_PER_SEC, step = 100000;
538 while (i && max) {
539 max -= step;
540 sleep_usec(step);
541 i = 0;
542 int j;
543 + pthread_mutex_lock(&ebpf_exit_cleanup);
544 for (j = 0; ebpf_threads[j].name != NULL; j++) {
527 - if (ebpf_threads[j].enabled != NETDATA_MAIN_THREAD_EXITED)
545 + if (ebpf_threads[j].enabled != NETDATA_THREAD_EBPF_STOPPED)
546 i++;
547 }
548 + pthread_mutex_unlock(&ebpf_exit_cleanup);
549 }
550
551 //Unload threads(except sync and filesystem)
552 + pthread_mutex_lock(&ebpf_exit_cleanup);
553 for (i = 0; ebpf_threads[i].name != NULL; i++) {
534 - if (ebpf_threads[i].enabled == NETDATA_MAIN_THREAD_EXITED && i != EBPF_MODULE_FILESYSTEM_IDX &&
554 + if (ebpf_threads[i].enabled == NETDATA_THREAD_EBPF_STOPPED && i != EBPF_MODULE_FILESYSTEM_IDX &&
555 i != EBPF_MODULE_SYNC_IDX)
556 ebpf_unload_legacy_code(ebpf_modules[i].objects, ebpf_modules[i].probe_links);
557 }
558 + pthread_mutex_unlock(&ebpf_exit_cleanup);
559
560 //Unload filesystem
540 - if (ebpf_threads[EBPF_MODULE_FILESYSTEM_IDX].enabled == NETDATA_MAIN_THREAD_EXITED) {
561 + pthread_mutex_lock(&ebpf_exit_cleanup);
562 + if (ebpf_threads[EBPF_MODULE_FILESYSTEM_IDX].enabled == NETDATA_THREAD_EBPF_STOPPED) {
563 for (i = 0; localfs[i].filesystem != NULL; i++) {
564 ebpf_unload_legacy_code(localfs[i].objects, localfs[i].probe_links);
565 }
566 }
567 + pthread_mutex_unlock(&ebpf_exit_cleanup);
568
569 //Unload Sync
547 - if (ebpf_threads[EBPF_MODULE_SYNC_IDX].enabled == NETDATA_MAIN_THREAD_EXITED) {
570 + pthread_mutex_lock(&ebpf_exit_cleanup);
571 + if (ebpf_threads[EBPF_MODULE_SYNC_IDX].enabled == NETDATA_THREAD_EBPF_STOPPED) {
572 for (i = 0; local_syscalls[i].syscall != NULL; i++) {
573 ebpf_unload_legacy_code(local_syscalls[i].objects, local_syscalls[i].probe_links);
574 }
575 }
576 + pthread_mutex_unlock(&ebpf_exit_cleanup);
577
553 - ebpf_exit(sig);
578 + ebpf_exit();
579 }
580
581 /*****************************************************************
@@ -1310,6 +1335,7 @@ static void read_local_addresses()
1335 int ebpf_start_pthread_variables()
1336 {
1337 pthread_mutex_init(&lock, NULL);
1338 + pthread_mutex_init(&ebpf_exit_cleanup, NULL);
1339 pthread_mutex_init(&collect_data_mutex, NULL);
1340
1341 if (pthread_cond_init(&collect_data_cond_var, NULL)) {
@@ -1954,7 +1980,7 @@ static void ebpf_parse_args(int argc, char **argv)
1980 &apps_groups_default_target, &apps_groups_root_target, ebpf_stock_config_dir, "groups")) {
1981 error("Cannot read process groups '%s/apps_groups.conf'. There are no internal defaults. Failing.",
1982 ebpf_stock_config_dir);
1957 - ebpf_exit(1);
1983 + ebpf_exit();
1984 }
1985 } else
1986 info("Loaded config file '%s/apps_groups.conf'", ebpf_user_config_dir);
@@ -2133,6 +2159,7 @@ static void ebpf_manage_pid(pid_t pid)
2159 int main(int argc, char **argv)
2160 {
2161 clocks_init();
2162 + main_thread_id = gettid();
2163
2164 set_global_variables();
2165 ebpf_parse_args(argc, argv);
@@ -2173,7 +2200,7 @@ int main(int argc, char **argv)
2200
2201 if (ebpf_start_pthread_variables()) {
2202 error("Cannot start mutex to control overall charts.");
2176 - ebpf_exit(5);
2203 + ebpf_exit();
2204 }
2205
2206 netdata_configured_host_prefix = getenv("NETDATA_HOST_PREFIX");
@@ -2196,18 +2223,25 @@ int main(int argc, char **argv)
2223 int i;
2224 for (i = 0; ebpf_threads[i].name != NULL; i++) {
2225 struct netdata_static_thread *st = &ebpf_threads[i];
2199 - st->thread = mallocz(sizeof(netdata_thread_t));
2226
2227 ebpf_module_t *em = &ebpf_modules[i];
2202 - em->thread_id = i;
2203 - netdata_thread_create(st->thread, st->name, NETDATA_THREAD_OPTION_DEFAULT, st->start_routine, em);
2228 + em->thread = st;
2229 + // We always initialize process, because it is responsible to take care of apps integration
2230 + if (em->enabled || !i) {
2231 + st->thread = mallocz(sizeof(netdata_thread_t));
2232 + em->thread_id = i;
2233 + st->enabled = NETDATA_THREAD_EBPF_RUNNING;
2234 + netdata_thread_create(st->thread, st->name, NETDATA_THREAD_OPTION_DEFAULT, st->start_routine, em);
2235 + } else {
2236 + st->enabled = NETDATA_THREAD_EBPF_STOPPED;
2237 + }
2238 }
2239
2206 - usec_t step = 60 * USEC_PER_SEC;
2240 + usec_t step = EBPF_DEFAULT_UPDATE_EVERY * USEC_PER_SEC;
2241 heartbeat_t hb;
2242 heartbeat_init(&hb);
2243 //Plugin will be killed when it receives a signal
2210 - for (;;) {
2244 + while (!ebpf_exit_plugin) {
2245 (void)heartbeat_next(&hb, step);
2246 }
2247
collectors/ebpf.plugin/ebpf.h
+1
@@ -168,6 +168,7 @@ void *ebpf_socket_thread(void *ptr);
168
169 // Common variables
170 extern pthread_mutex_t lock;
171 +extern pthread_mutex_t ebpf_exit_cleanup;
172 extern int ebpf_nprocs;
173 extern int running_on_kernel;
174 extern int isrh;
collectors/ebpf.plugin/ebpf_cachestat.c
+39 -35
@@ -44,7 +44,6 @@ struct config cachestat_config = { .first_section = NULL,
44 .mutex = NETDATA_MUTEX_INITIALIZER,
45 .index = { .avl_tree = { .root = NULL, .compar = appconfig_section_compare },
46 .rwlock = AVL_LOCK_INITIALIZER } };
47 -static enum ebpf_threads_status ebpf_cachestat_exited = NETDATA_THREAD_EBPF_RUNNING;
47
48 netdata_ebpf_targets_t cachestat_targets[] = { {.name = "add_to_page_cache_lru", .mode = EBPF_LOAD_TRAMPOLINE},
49 {.name = "mark_page_accessed", .mode = EBPF_LOAD_TRAMPOLINE},
@@ -322,6 +321,38 @@ static inline int ebpf_cachestat_load_and_attach(struct cachestat_bpf *obj, ebpf
321 *
322 *****************************************************************/
323
324 +/**
325 + * Cachestat Free
326 + *
327 + * Cleanup variables after child threads to stop
328 + *
329 + * @param ptr thread data.
330 + */
331 +static void ebpf_cachestat_free(ebpf_module_t *em)
332 +{
333 + pthread_mutex_lock(&ebpf_exit_cleanup);
334 + if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) {
335 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
336 + pthread_mutex_unlock(&ebpf_exit_cleanup);
337 + return;
338 + }
339 + pthread_mutex_unlock(&ebpf_exit_cleanup);
340 +
341 + ebpf_cleanup_publish_syscall(cachestat_counter_publish_aggregated);
342 +
343 + freez(cachestat_vector);
344 + freez(cachestat_values);
345 + freez(cachestat_threads.thread);
346 +
347 +#ifdef LIBBPF_MAJOR_VERSION
348 + if (bpf_obj)
349 + cachestat_bpf__destroy(bpf_obj);
350 +#endif
351 + pthread_mutex_lock(&ebpf_exit_cleanup);
352 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
353 + pthread_mutex_unlock(&ebpf_exit_cleanup);
354 +}
355 +
356 /**
357 * Cachestat exit.
358 *
@@ -332,12 +363,8 @@ static inline int ebpf_cachestat_load_and_attach(struct cachestat_bpf *obj, ebpf
363 static void ebpf_cachestat_exit(void *ptr)
364 {
365 ebpf_module_t *em = (ebpf_module_t *)ptr;
335 - if (!em->enabled) {
336 - em->enabled = NETDATA_MAIN_THREAD_EXITED;
337 - return;
338 - }
339 -
340 - ebpf_cachestat_exited = NETDATA_THREAD_EBPF_STOPPING;
366 + netdata_thread_cancel(*cachestat_threads.thread);
367 + ebpf_cachestat_free(em);
368 }
369
370 /**
@@ -350,21 +377,7 @@ static void ebpf_cachestat_exit(void *ptr)
377 static void ebpf_cachestat_cleanup(void *ptr)
378 {
379 ebpf_module_t *em = (ebpf_module_t *)ptr;
353 - if (ebpf_cachestat_exited != NETDATA_THREAD_EBPF_STOPPED)
354 - return;
355 -
356 - ebpf_cleanup_publish_syscall(cachestat_counter_publish_aggregated);
357 -
358 - freez(cachestat_vector);
359 - freez(cachestat_values);
360 - freez(cachestat_threads.thread);
361 -
362 -#ifdef LIBBPF_MAJOR_VERSION
363 - if (bpf_obj)
364 - cachestat_bpf__destroy(bpf_obj);
365 -#endif
366 - cachestat_threads.enabled = NETDATA_MAIN_THREAD_EXITED;
367 - em->enabled = NETDATA_MAIN_THREAD_EXITED;
380 + ebpf_cachestat_free(em);
381 }
382
383 /*****************************************************************
@@ -682,17 +695,12 @@ void *ebpf_cachestat_read_hash(void *ptr)
695 ebpf_module_t *em = (ebpf_module_t *)ptr;
696
697 usec_t step = NETDATA_LATENCY_CACHESTAT_SLEEP_MS * em->update_every;
685 - while (ebpf_cachestat_exited == NETDATA_THREAD_EBPF_RUNNING) {
686 - usec_t dt = heartbeat_next(&hb, step);
687 - (void)dt;
688 - if (ebpf_cachestat_exited == NETDATA_THREAD_EBPF_STOPPING)
689 - break;
698 + while (!ebpf_exit_plugin) {
699 + (void)heartbeat_next(&hb, step);
700
701 read_global_table();
702 }
703
694 - ebpf_cachestat_exited = NETDATA_THREAD_EBPF_STOPPED;
695 -
704 netdata_thread_cleanup_pop(1);
705 return NULL;
706 }
@@ -1292,16 +1300,13 @@ void *ebpf_cachestat_thread(void *ptr)
1300
1301 ebpf_update_pid_table(&cachestat_maps[NETDATA_CACHESTAT_PID_STATS], em);
1302
1295 - if (!em->enabled)
1296 - goto endcachestat;
1297 -
1303 ebpf_cachestat_set_internal_value();
1304
1305 #ifdef LIBBPF_MAJOR_VERSION
1306 ebpf_adjust_thread_load(em, default_btf);
1307 #endif
1308 if (ebpf_cachestat_load_bpf(em)) {
1304 - em->enabled = CONFIG_BOOLEAN_NO;
1309 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
1310 goto endcachestat;
1311 }
1312
@@ -1323,8 +1328,7 @@ void *ebpf_cachestat_thread(void *ptr)
1328 cachestat_collector(em);
1329
1330 endcachestat:
1326 - if (!em->enabled)
1327 - ebpf_update_disabled_plugin_stats(em);
1331 + ebpf_update_disabled_plugin_stats(em);
1332
1333 netdata_thread_cleanup_pop(1);
1334 return NULL;
collectors/ebpf.plugin/ebpf_dcstat.c
+40 -36
@@ -27,7 +27,6 @@ struct netdata_static_thread dcstat_threads = {"DCSTAT KERNEL",
27 .thread = NULL,
28 .init_routine = NULL,
29 .start_routine = NULL};
30 -static enum ebpf_threads_status ebpf_dcstat_exited = NETDATA_THREAD_EBPF_RUNNING;
30
31 ebpf_local_maps_t dcstat_maps[] = {{.name = "dcstat_global", .internal_input = NETDATA_DIRECTORY_CACHE_END,
32 .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
@@ -295,33 +294,21 @@ void ebpf_dcstat_clean_names()
294 }
295
296 /**
298 - * DCstat exit
297 + * DCstat Free
298 *
300 - * Cancel child and exit.
299 + * Cleanup variables after child threads to stop
300 *
301 * @param ptr thread data.
302 */
304 -static void ebpf_dcstat_exit(void *ptr)
303 +static void ebpf_dcstat_free(ebpf_module_t *em )
304 {
306 - ebpf_module_t *em = (ebpf_module_t *)ptr;
307 - if (!em->enabled) {
308 - em->enabled = NETDATA_MAIN_THREAD_EXITED;
305 + pthread_mutex_lock(&ebpf_exit_cleanup);
306 + if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) {
307 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
308 + pthread_mutex_unlock(&ebpf_exit_cleanup);
309 return;
310 }
311 -
312 - ebpf_dcstat_exited = NETDATA_THREAD_EBPF_STOPPING;
313 -}
314 -
315 -/**
316 - * Clean up the main thread.
317 - *
318 - * @param ptr thread data.
319 - */
320 -static void ebpf_dcstat_cleanup(void *ptr)
321 -{
322 - ebpf_module_t *em = (ebpf_module_t *)ptr;
323 - if (ebpf_dcstat_exited != NETDATA_THREAD_EBPF_STOPPED)
324 - return;
311 + pthread_mutex_unlock(&ebpf_exit_cleanup);
312
313 freez(dcstat_vector);
314 freez(dcstat_values);
@@ -336,8 +323,34 @@ static void ebpf_dcstat_cleanup(void *ptr)
323 dc_bpf__destroy(bpf_obj);
324 #endif
325
339 - dcstat_threads.enabled = NETDATA_MAIN_THREAD_EXITED;
340 - em->enabled = NETDATA_MAIN_THREAD_EXITED;
326 + pthread_mutex_lock(&ebpf_exit_cleanup);
327 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
328 + pthread_mutex_unlock(&ebpf_exit_cleanup);
329 +}
330 +
331 +/**
332 + * DCstat exit
333 + *
334 + * Cancel child and exit.
335 + *
336 + * @param ptr thread data.
337 + */
338 +static void ebpf_dcstat_exit(void *ptr)
339 +{
340 + ebpf_module_t *em = (ebpf_module_t *)ptr;
341 + netdata_thread_cancel(*dcstat_threads.thread);
342 + ebpf_dcstat_free(em);
343 +}
344 +
345 +/**
346 + * Clean up the main thread.
347 + *
348 + * @param ptr thread data.
349 + */
350 +static void ebpf_dcstat_cleanup(void *ptr)
351 +{
352 + ebpf_module_t *em = (ebpf_module_t *)ptr;
353 + ebpf_dcstat_free(em);
354 }
355
356 /*****************************************************************
@@ -564,17 +577,12 @@ void *ebpf_dcstat_read_hash(void *ptr)
577 ebpf_module_t *em = (ebpf_module_t *)ptr;
578
579 usec_t step = NETDATA_LATENCY_DCSTAT_SLEEP_MS * em->update_every;
567 - while (ebpf_dcstat_exited == NETDATA_THREAD_EBPF_RUNNING) {
568 - usec_t dt = heartbeat_next(&hb, step);
569 - (void)dt;
570 - if (ebpf_dcstat_exited == NETDATA_THREAD_EBPF_STOPPING)
571 - break;
580 + while (!ebpf_exit_plugin) {
581 + (void)heartbeat_next(&hb, step);
582
583 read_global_table();
584 }
585
576 - ebpf_dcstat_exited = NETDATA_THREAD_EBPF_STOPPED;
577 -
586 netdata_thread_cleanup_pop(1);
587 return NULL;
588 }
@@ -1183,14 +1191,11 @@ void *ebpf_dcstat_thread(void *ptr)
1191
1192 ebpf_update_names(dc_optional_name, em);
1193
1186 - if (!em->enabled)
1187 - goto enddcstat;
1188 -
1194 #ifdef LIBBPF_MAJOR_VERSION
1195 ebpf_adjust_thread_load(em, default_btf);
1196 #endif
1197 if (ebpf_dcstat_load_bpf(em)) {
1193 - em->enabled = CONFIG_BOOLEAN_NO;
1198 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
1199 goto enddcstat;
1200 }
1201
@@ -1213,8 +1218,7 @@ void *ebpf_dcstat_thread(void *ptr)
1218 dcstat_collector(em);
1219
1220 enddcstat:
1216 - if (!em->enabled)
1217 - ebpf_update_disabled_plugin_stats(em);
1221 + ebpf_update_disabled_plugin_stats(em);
1222
1223 netdata_thread_cleanup_pop(1);
1224 return NULL;
collectors/ebpf.plugin/ebpf_disk.c
+44 -40
@@ -43,7 +43,6 @@ static struct netdata_static_thread disk_threads = {
43 .init_routine = NULL,
44 .start_routine = NULL
45 };
46 -static enum ebpf_threads_status ebpf_disk_exited = NETDATA_THREAD_EBPF_RUNNING;
46
47 ebpf_publish_disk_t *plot_disks = NULL;
48 pthread_mutex_t plot_mutex;
@@ -430,6 +429,40 @@ static void ebpf_cleanup_disk_list()
429 }
430 }
431
432 +/**
433 + * DISK Free
434 + *
435 + * Cleanup variables after child threads to stop
436 + *
437 + * @param ptr thread data.
438 + */
439 +static void ebpf_disk_free(ebpf_module_t *em)
440 +{
441 + pthread_mutex_lock(&ebpf_exit_cleanup);
442 + if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) {
443 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
444 + pthread_mutex_unlock(&ebpf_exit_cleanup);
445 + return;
446 + }
447 + pthread_mutex_unlock(&ebpf_exit_cleanup);
448 +
449 + ebpf_disk_disable_tracepoints();
450 +
451 + if (dimensions)
452 + ebpf_histogram_dimension_cleanup(dimensions, NETDATA_EBPF_HIST_MAX_BINS);
453 +
454 + freez(disk_hash_values);
455 + freez(disk_threads.thread);
456 + pthread_mutex_destroy(&plot_mutex);
457 +
458 + ebpf_cleanup_plot_disks();
459 + ebpf_cleanup_disk_list();
460 +
461 + pthread_mutex_lock(&ebpf_exit_cleanup);
462 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
463 + pthread_mutex_unlock(&ebpf_exit_cleanup);
464 +}
465 +
466 /**
467 * Disk exit.
468 *
@@ -440,12 +473,8 @@ static void ebpf_cleanup_disk_list()
473 static void ebpf_disk_exit(void *ptr)
474 {
475 ebpf_module_t *em = (ebpf_module_t *)ptr;
443 - if (!em->enabled) {
444 - em->enabled = NETDATA_MAIN_THREAD_EXITED;
445 - return;
446 - }
447 -
448 - ebpf_disk_exited = NETDATA_THREAD_EBPF_STOPPING;
476 + netdata_thread_cancel(*disk_threads.thread);
477 + ebpf_disk_free(em);
478 }
479
480 /**
@@ -458,23 +487,7 @@ static void ebpf_disk_exit(void *ptr)
487 static void ebpf_disk_cleanup(void *ptr)
488 {
489 ebpf_module_t *em = (ebpf_module_t *)ptr;
461 - if (ebpf_disk_exited != NETDATA_THREAD_EBPF_STOPPED)
462 - return;
463 -
464 - ebpf_disk_disable_tracepoints();
465 -
466 - if (dimensions)
467 - ebpf_histogram_dimension_cleanup(dimensions, NETDATA_EBPF_HIST_MAX_BINS);
468 -
469 - freez(disk_hash_values);
470 - freez(disk_threads.thread);
471 - pthread_mutex_destroy(&plot_mutex);
472 -
473 - ebpf_cleanup_plot_disks();
474 - ebpf_cleanup_disk_list();
475 -
476 - disk_threads.enabled = NETDATA_MAIN_THREAD_EXITED;
477 - em->enabled = NETDATA_MAIN_THREAD_EXITED;
490 + ebpf_disk_free(em);
491 }
492
493 /*****************************************************************
@@ -597,17 +610,12 @@ void *ebpf_disk_read_hash(void *ptr)
610 ebpf_module_t *em = (ebpf_module_t *)ptr;
611
612 usec_t step = NETDATA_LATENCY_DISK_SLEEP_MS * em->update_every;
600 - while (ebpf_disk_exited == NETDATA_THREAD_EBPF_RUNNING) {
601 - usec_t dt = heartbeat_next(&hb, step);
602 - (void)dt;
603 - if (ebpf_disk_exited == NETDATA_THREAD_EBPF_STOPPING)
604 - break;
613 + while (!ebpf_exit_plugin) {
614 + (void)heartbeat_next(&hb, step);
615
616 read_hard_disk_tables(disk_maps[NETDATA_DISK_READ].map_fd);
617 }
618
609 - ebpf_disk_exited = NETDATA_THREAD_EBPF_STOPPED;
610 -
619 netdata_thread_cleanup_pop(1);
620 return NULL;
621 }
@@ -812,29 +820,26 @@ void *ebpf_disk_thread(void *ptr)
820 ebpf_module_t *em = (ebpf_module_t *)ptr;
821 em->maps = disk_maps;
822
815 - if (!em->enabled)
816 - goto enddisk;
817 -
823 if (ebpf_disk_enable_tracepoints()) {
819 - em->enabled = CONFIG_BOOLEAN_NO;
824 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
825 goto enddisk;
826 }
827
828 avl_init_lock(&disk_tree, ebpf_compare_disks);
829 if (read_local_disks()) {
825 - em->enabled = CONFIG_BOOLEAN_NO;
830 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
831 goto enddisk;
832 }
833
834 if (pthread_mutex_init(&plot_mutex, NULL)) {
830 - em->enabled = 0;
835 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
836 error("Cannot initialize local mutex");
837 goto enddisk;
838 }
839
840 em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
841 if (!em->probe_links) {
837 - em->enabled = 0;
842 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
843 goto enddisk;
844 }
845
@@ -852,8 +857,7 @@ void *ebpf_disk_thread(void *ptr)
857 disk_collector(em);
858
859 enddisk:
855 - if (!em->enabled)
856 - ebpf_update_disabled_plugin_stats(em);
860 + ebpf_update_disabled_plugin_stats(em);
861
862 netdata_thread_cleanup_pop(1);
863
collectors/ebpf.plugin/ebpf_fd.c
+41 -35
@@ -38,7 +38,6 @@ struct netdata_static_thread fd_thread = {"FD KERNEL",
38 .init_routine = NULL,
39 .start_routine = NULL};
40
41 -static enum ebpf_threads_status ebpf_fd_exited = NETDATA_THREAD_EBPF_RUNNING;
41 static netdata_idx_t fd_hash_values[NETDATA_FD_COUNTER];
42 static netdata_idx_t *fd_values = NULL;
43
@@ -331,6 +330,38 @@ static inline int ebpf_fd_load_and_attach(struct fd_bpf *obj, ebpf_module_t *em)
330 *
331 *****************************************************************/
332
333 +/**
334 + * FD Free
335 + *
336 + * Cleanup variables after child threads to stop
337 + *
338 + * @param ptr thread data.
339 + */
340 +static void ebpf_fd_free(ebpf_module_t *em)
341 +{
342 + pthread_mutex_lock(&ebpf_exit_cleanup);
343 + if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) {
344 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
345 + pthread_mutex_unlock(&ebpf_exit_cleanup);
346 + return;
347 + }
348 + pthread_mutex_unlock(&ebpf_exit_cleanup);
349 +
350 + ebpf_cleanup_publish_syscall(fd_publish_aggregated);
351 + freez(fd_thread.thread);
352 + freez(fd_values);
353 + freez(fd_vector);
354 +
355 +#ifdef LIBBPF_MAJOR_VERSION
356 + if (bpf_obj)
357 + fd_bpf__destroy(bpf_obj);
358 +#endif
359 +
360 + pthread_mutex_lock(&ebpf_exit_cleanup);
361 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
362 + pthread_mutex_unlock(&ebpf_exit_cleanup);
363 +}
364 +
365 /**
366 * FD Exit
367 *
@@ -341,12 +372,8 @@ static inline int ebpf_fd_load_and_attach(struct fd_bpf *obj, ebpf_module_t *em)
372 static void ebpf_fd_exit(void *ptr)
373 {
374 ebpf_module_t *em = (ebpf_module_t *)ptr;
344 - if (!em->enabled) {
345 - em->enabled = NETDATA_MAIN_THREAD_EXITED;
346 - return;
347 - }
348 -
349 - ebpf_fd_exited = NETDATA_THREAD_EBPF_STOPPING;
375 + netdata_thread_cancel(*fd_thread.thread);
376 + ebpf_fd_free(em);
377 }
378
379 /**
@@ -357,21 +384,7 @@ static void ebpf_fd_exit(void *ptr)
384 static void ebpf_fd_cleanup(void *ptr)
385 {
386 ebpf_module_t *em = (ebpf_module_t *)ptr;
360 - if (ebpf_fd_exited != NETDATA_THREAD_EBPF_STOPPED)
361 - return;
362 -
363 - ebpf_cleanup_publish_syscall(fd_publish_aggregated);
364 - freez(fd_thread.thread);
365 - freez(fd_values);
366 - freez(fd_vector);
367 -
368 -#ifdef LIBBPF_MAJOR_VERSION
369 - if (bpf_obj)
370 - fd_bpf__destroy(bpf_obj);
371 -#endif
372 -
373 - fd_thread.enabled = NETDATA_MAIN_THREAD_EXITED;
374 - em->enabled = NETDATA_MAIN_THREAD_EXITED;
387 + ebpf_fd_free(em);
388 }
389
390 /*****************************************************************
@@ -445,17 +458,12 @@ void *ebpf_fd_read_hash(void *ptr)
458
459 ebpf_module_t *em = (ebpf_module_t *)ptr;
460 usec_t step = NETDATA_FD_SLEEP_MS * em->update_every;
448 - while (ebpf_fd_exited == NETDATA_THREAD_EBPF_RUNNING) {
449 - usec_t dt = heartbeat_next(&hb, step);
450 - (void)dt;
451 - if (ebpf_fd_exited == NETDATA_THREAD_EBPF_STOPPING)
452 - break;
461 + while (!ebpf_exit_plugin) {
462 + (void)heartbeat_next(&hb, step);
463
464 read_global_table();
465 }
466
457 - ebpf_fd_exited = NETDATA_THREAD_EBPF_STOPPED;
458 -
467 netdata_thread_cleanup_pop(1);
468 return NULL;
469 }
@@ -1143,14 +1151,13 @@ void *ebpf_fd_thread(void *ptr)
1151 ebpf_module_t *em = (ebpf_module_t *)ptr;
1152 em->maps = fd_maps;
1153
1146 - if (!em->enabled)
1147 - goto endfd;
1148 -
1154 #ifdef LIBBPF_MAJOR_VERSION
1155 ebpf_adjust_thread_load(em, default_btf);
1156 #endif
1152 - if (ebpf_fd_load_bpf(em))
1157 + if (ebpf_fd_load_bpf(em)) {
1158 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
1159 goto endfd;
1160 + }
1161
1162 ebpf_fd_allocate_global_vectors(em->apps_charts);
1163
@@ -1169,8 +1176,7 @@ void *ebpf_fd_thread(void *ptr)
1176 fd_collector(em);
1177
1178 endfd:
1172 - if (!em->enabled)
1173 - ebpf_update_disabled_plugin_stats(em);
1179 + ebpf_update_disabled_plugin_stats(em);
1180
1181 netdata_thread_cleanup_pop(1);
1182 return NULL;
collectors/ebpf.plugin/ebpf_filesystem.c
+37 -45
@@ -41,8 +41,6 @@ struct netdata_static_thread filesystem_threads = {
41 .start_routine = NULL
42 };
43
44 -static enum ebpf_threads_status ebpf_fs_exited = NETDATA_THREAD_EBPF_RUNNING;
45 -
44 static netdata_syscall_stat_t filesystem_aggregated_data[NETDATA_EBPF_HIST_MAX_BINS];
45 static netdata_publish_syscall_t filesystem_publish_aggregated[NETDATA_EBPF_HIST_MAX_BINS];
46
@@ -325,21 +323,40 @@ void ebpf_filesystem_cleanup_ebpf_data()
323
324 freez(efp->hadditional.name);
325 freez(efp->hadditional.title);
328 -
329 - struct bpf_link **probe_links = efp->probe_links;
330 - size_t j = 0 ;
331 - struct bpf_program *prog;
332 - bpf_object__for_each_program(prog, efp->objects) {
333 - bpf_link__destroy(probe_links[j]);
334 - j++;
335 - }
336 - freez(probe_links);
337 - if (efp->objects)
338 - bpf_object__close(efp->objects);
326 }
327 }
328 }
329
330 +/**
331 + * Filesystem Free
332 + *
333 + * Cleanup variables after child threads to stop
334 + *
335 + * @param ptr thread data.
336 + */
337 +static void ebpf_filesystem_free(ebpf_module_t *em)
338 +{
339 + pthread_mutex_lock(&ebpf_exit_cleanup);
340 + if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) {
341 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
342 + pthread_mutex_unlock(&ebpf_exit_cleanup);
343 + return;
344 + }
345 + pthread_mutex_unlock(&ebpf_exit_cleanup);
346 +
347 + freez(filesystem_threads.thread);
348 + ebpf_cleanup_publish_syscall(filesystem_publish_aggregated);
349 +
350 + ebpf_filesystem_cleanup_ebpf_data();
351 + if (dimensions)
352 + ebpf_histogram_dimension_cleanup(dimensions, NETDATA_EBPF_HIST_MAX_BINS);
353 + freez(filesystem_hash_values);
354 +
355 + pthread_mutex_lock(&ebpf_exit_cleanup);
356 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
357 + pthread_mutex_unlock(&ebpf_exit_cleanup);
358 +}
359 +
360 /**
361 * Filesystem exit
362 *
@@ -350,12 +367,8 @@ void ebpf_filesystem_cleanup_ebpf_data()
367 static void ebpf_filesystem_exit(void *ptr)
368 {
369 ebpf_module_t *em = (ebpf_module_t *)ptr;
353 - if (!em->enabled) {
354 - em->enabled = NETDATA_MAIN_THREAD_EXITED;
355 - return;
356 - }
357 -
358 - ebpf_fs_exited = NETDATA_THREAD_EBPF_STOPPING;
370 + netdata_thread_cancel(*filesystem_threads.thread);
371 + ebpf_filesystem_free(em);
372 }
373
374 /**
@@ -368,19 +381,7 @@ static void ebpf_filesystem_exit(void *ptr)
381 static void ebpf_filesystem_cleanup(void *ptr)
382 {
383 ebpf_module_t *em = (ebpf_module_t *)ptr;
371 - if (ebpf_fs_exited != NETDATA_THREAD_EBPF_STOPPED)
372 - return;
373 -
374 - freez(filesystem_threads.thread);
375 - ebpf_cleanup_publish_syscall(filesystem_publish_aggregated);
376 -
377 - ebpf_filesystem_cleanup_ebpf_data();
378 - if (dimensions)
379 - ebpf_histogram_dimension_cleanup(dimensions, NETDATA_EBPF_HIST_MAX_BINS);
380 - freez(filesystem_hash_values);
381 -
382 - filesystem_threads.enabled = NETDATA_MAIN_THREAD_EXITED;
383 - em->enabled = NETDATA_MAIN_THREAD_EXITED;
384 + ebpf_filesystem_free(em);
385 }
386
387 /*****************************************************************
@@ -491,11 +492,8 @@ void *ebpf_filesystem_read_hash(void *ptr)
492 heartbeat_init(&hb);
493 usec_t step = NETDATA_FILESYSTEM_READ_SLEEP_MS * em->update_every;
494 int update_every = em->update_every;
494 - while (ebpf_fs_exited == NETDATA_THREAD_EBPF_RUNNING) {
495 - usec_t dt = heartbeat_next(&hb, step);
496 - (void)dt;
497 - if (ebpf_fs_exited == NETDATA_THREAD_EBPF_STOPPING)
498 - break;
495 + while (!ebpf_exit_plugin) {
496 + (void)heartbeat_next(&hb, step);
497
498 (void) ebpf_update_partitions(em);
499 ebpf_obsolete_fs_charts(update_every);
@@ -507,8 +505,6 @@ void *ebpf_filesystem_read_hash(void *ptr)
505 read_filesystem_tables();
506 }
507
510 - ebpf_fs_exited = NETDATA_THREAD_EBPF_STOPPED;
511 -
508 netdata_thread_cleanup_pop(1);
509 return NULL;
510 }
@@ -611,9 +607,6 @@ void *ebpf_filesystem_thread(void *ptr)
607 em->maps = fs_maps;
608 ebpf_update_filesystem();
609
614 - if (!em->enabled)
615 - goto endfilesystem;
616 -
610 // Initialize optional as zero, to identify when there are not partitions to monitor
611 em->optional = 0;
612
@@ -621,7 +614,7 @@ void *ebpf_filesystem_thread(void *ptr)
614 if (em->optional)
615 info("Netdata cannot monitor the filesystems used on this host.");
616
624 - em->enabled = CONFIG_BOOLEAN_NO;
617 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
618 goto endfilesystem;
619 }
620
@@ -638,8 +631,7 @@ void *ebpf_filesystem_thread(void *ptr)
631 filesystem_collector(em);
632
633 endfilesystem:
641 - if (!em->enabled)
642 - ebpf_update_disabled_plugin_stats(em);
634 + ebpf_update_disabled_plugin_stats(em);
635
636 netdata_thread_cleanup_pop(1);
637 return NULL;
collectors/ebpf.plugin/ebpf_hardirq.c
+35 -34
@@ -145,7 +145,33 @@ static struct netdata_static_thread hardirq_threads = {
145 .init_routine = NULL,
146 .start_routine = NULL
147 };
148 -static enum ebpf_threads_status ebpf_hardirq_exited = NETDATA_THREAD_EBPF_RUNNING;
148 +
149 +/**
150 + * Hardirq Free
151 + *
152 + * Cleanup variables after child threads to stop
153 + *
154 + * @param ptr thread data.
155 + */
156 +static void ebpf_hardirq_free(ebpf_module_t *em)
157 +{
158 + pthread_mutex_lock(&ebpf_exit_cleanup);
159 + if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) {
160 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
161 + pthread_mutex_unlock(&ebpf_exit_cleanup);
162 + return;
163 + }
164 + pthread_mutex_unlock(&ebpf_exit_cleanup);
165 +
166 + freez(hardirq_threads.thread);
167 + for (int i = 0; hardirq_tracepoints[i].class != NULL; i++) {
168 + ebpf_disable_tracepoint(&hardirq_tracepoints[i]);
169 + }
170 + freez(hardirq_ebpf_vals);
171 + freez(hardirq_ebpf_static_vals);
172 +
173 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
174 +}
175
176 /**
177 * Hardirq Exit
@@ -157,12 +183,8 @@ static enum ebpf_threads_status ebpf_hardirq_exited = NETDATA_THREAD_EBPF_RUNNIN
183 static void hardirq_exit(void *ptr)
184 {
185 ebpf_module_t *em = (ebpf_module_t *)ptr;
160 - if (!em->enabled) {
161 - em->enabled = NETDATA_MAIN_THREAD_EXITED;
162 - return;
163 - }
164 -
165 - ebpf_hardirq_exited = NETDATA_THREAD_EBPF_STOPPING;
186 + netdata_thread_cancel(*hardirq_threads.thread);
187 + ebpf_hardirq_free(em);
188 }
189
190 /**
@@ -175,19 +197,7 @@ static void hardirq_exit(void *ptr)
197 static void hardirq_cleanup(void *ptr)
198 {
199 ebpf_module_t *em = (ebpf_module_t *)ptr;
178 -
179 - if (ebpf_hardirq_exited != NETDATA_THREAD_EBPF_STOPPED)
180 - return;
181 -
182 - freez(hardirq_threads.thread);
183 - for (int i = 0; hardirq_tracepoints[i].class != NULL; i++) {
184 - ebpf_disable_tracepoint(&hardirq_tracepoints[i]);
185 - }
186 - freez(hardirq_ebpf_vals);
187 - freez(hardirq_ebpf_static_vals);
188 -
189 - hardirq_threads.enabled = NETDATA_MAIN_THREAD_EXITED;
190 - em->enabled = NETDATA_MAIN_THREAD_EXITED;
200 + ebpf_hardirq_free(em);
201 }
202
203 /*****************************************************************
@@ -330,16 +340,12 @@ static void *hardirq_reader(void *ptr)
340 ebpf_module_t *em = (ebpf_module_t *)ptr;
341
342 usec_t step = NETDATA_HARDIRQ_SLEEP_MS * em->update_every;
333 - while (ebpf_hardirq_exited == NETDATA_THREAD_EBPF_RUNNING) {
334 - usec_t dt = heartbeat_next(&hb, step);
335 - UNUSED(dt);
336 - if (ebpf_hardirq_exited == NETDATA_THREAD_EBPF_STOPPING)
337 - break;
343 + while (!ebpf_exit_plugin) {
344 + (void)heartbeat_next(&hb, step);
345
346 hardirq_read_latency_map(hardirq_maps[HARDIRQ_MAP_LATENCY].map_fd);
347 hardirq_read_latency_static_map(hardirq_maps[HARDIRQ_MAP_LATENCY_STATIC].map_fd);
348 }
342 - ebpf_hardirq_exited = NETDATA_THREAD_EBPF_STOPPED;
349
350 netdata_thread_cleanup_pop(1);
351 return NULL;
@@ -479,26 +485,21 @@ void *ebpf_hardirq_thread(void *ptr)
485 ebpf_module_t *em = (ebpf_module_t *)ptr;
486 em->maps = hardirq_maps;
487
482 - if (!em->enabled) {
483 - goto endhardirq;
484 - }
485 -
488 if (ebpf_enable_tracepoints(hardirq_tracepoints) == 0) {
487 - em->enabled = CONFIG_BOOLEAN_NO;
489 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
490 goto endhardirq;
491 }
492
493 em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
494 if (!em->probe_links) {
493 - em->enabled = CONFIG_BOOLEAN_NO;
495 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
496 goto endhardirq;
497 }
498
499 hardirq_collector(em);
500
501 endhardirq:
500 - if (!em->enabled)
501 - ebpf_update_disabled_plugin_stats(em);
502 + ebpf_update_disabled_plugin_stats(em);
503
504 netdata_thread_cleanup_pop(1);
505
collectors/ebpf.plugin/ebpf_mdflush.c
+32 -27
@@ -45,7 +45,29 @@ static struct netdata_static_thread mdflush_threads = {
45 .init_routine = NULL,
46 .start_routine = NULL
47 };
48 -static enum ebpf_threads_status ebpf_mdflush_exited = NETDATA_THREAD_EBPF_RUNNING;
48 +
49 +/**
50 + * MDflush Free
51 + *
52 + * Cleanup variables after child threads to stop
53 + *
54 + * @param ptr thread data.
55 + */
56 +static void ebpf_mdflush_free(ebpf_module_t *em)
57 +{
58 + pthread_mutex_lock(&ebpf_exit_cleanup);
59 + if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) {
60 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
61 + pthread_mutex_unlock(&ebpf_exit_cleanup);
62 + return;
63 + }
64 + pthread_mutex_unlock(&ebpf_exit_cleanup);
65 +
66 + freez(mdflush_ebpf_vals);
67 + freez(mdflush_threads.thread);
68 +
69 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
70 +}
71
72 /**
73 * MDflush exit
@@ -57,12 +79,7 @@ static enum ebpf_threads_status ebpf_mdflush_exited = NETDATA_THREAD_EBPF_RUNNIN
79 static void mdflush_exit(void *ptr)
80 {
81 ebpf_module_t *em = (ebpf_module_t *)ptr;
60 - if (!em->enabled) {
61 - em->enabled = NETDATA_MAIN_THREAD_EXITED;
62 - return;
63 - }
64 -
65 - ebpf_mdflush_exited = NETDATA_THREAD_EBPF_STOPPING;
82 + ebpf_mdflush_free(em);
83 }
84
85 /**
@@ -75,14 +92,8 @@ static void mdflush_exit(void *ptr)
92 static void mdflush_cleanup(void *ptr)
93 {
94 ebpf_module_t *em = (ebpf_module_t *)ptr;
78 - if (ebpf_mdflush_exited != NETDATA_THREAD_EBPF_STOPPED)
79 - return;
80 -
81 - freez(mdflush_ebpf_vals);
82 - freez(mdflush_threads.thread);
83 -
84 - mdflush_threads.enabled = NETDATA_MAIN_THREAD_EXITED;
85 - em->enabled = NETDATA_MAIN_THREAD_EXITED;
95 + netdata_thread_cancel(*mdflush_threads.thread);
96 + ebpf_mdflush_free(em);
97 }
98
99 /**
@@ -189,17 +200,12 @@ static void *mdflush_reader(void *ptr)
200 ebpf_module_t *em = (ebpf_module_t *)ptr;
201
202 usec_t step = NETDATA_MDFLUSH_SLEEP_MS * em->update_every;
192 - while (ebpf_mdflush_exited == NETDATA_THREAD_EBPF_RUNNING) {
193 - usec_t dt = heartbeat_next(&hb, step);
194 - UNUSED(dt);
195 - if (ebpf_mdflush_exited == NETDATA_THREAD_EBPF_STOPPING)
196 - break;
203 + while (!ebpf_exit_plugin) {
204 + (void)heartbeat_next(&hb, step);
205
206 mdflush_read_count_map();
207 }
208
201 - ebpf_mdflush_exited = NETDATA_THREAD_EBPF_STOPPED;
202 -
209 netdata_thread_cleanup_pop(1);
210 return NULL;
211 }
@@ -302,26 +308,25 @@ void *ebpf_mdflush_thread(void *ptr)
308
309 char *md_flush_request = ebpf_find_symbol("md_flush_request");
310 if (!md_flush_request) {
305 - em->enabled = CONFIG_BOOLEAN_NO;
311 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
312 error("Cannot monitor MD devices, because md is not loaded.");
313 }
314 freez(md_flush_request);
315
310 - if (!em->enabled) {
316 + if (em->thread->enabled == NETDATA_THREAD_EBPF_STOPPED) {
317 goto endmdflush;
318 }
319
320 em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
321 if (!em->probe_links) {
316 - em->enabled = CONFIG_BOOLEAN_NO;
322 + em->enabled = NETDATA_THREAD_EBPF_STOPPED;
323 goto endmdflush;
324 }
325
326 mdflush_collector(em);
327
328 endmdflush:
323 - if (!em->enabled)
324 - ebpf_update_disabled_plugin_stats(em);
329 + ebpf_update_disabled_plugin_stats(em);
330
331 netdata_thread_cleanup_pop(1);
332
collectors/ebpf.plugin/ebpf_mount.c
+37 -33
@@ -36,7 +36,6 @@ struct netdata_static_thread mount_thread = {
36 netdata_ebpf_targets_t mount_targets[] = { {.name = "mount", .mode = EBPF_LOAD_TRAMPOLINE},
37 {.name = "umount", .mode = EBPF_LOAD_TRAMPOLINE},
38 {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
39 -static enum ebpf_threads_status ebpf_mount_exited = NETDATA_THREAD_EBPF_RUNNING;
39
40 #ifdef LIBBPF_MAJOR_VERSION
41 #include "includes/mount.skel.h" // BTF code
@@ -230,6 +229,36 @@ static inline int ebpf_mount_load_and_attach(struct mount_bpf *obj, ebpf_module_
229 *
230 *****************************************************************/
231
232 +/**
233 + * Mount Free
234 + *
235 + * Cleanup variables after child threads to stop
236 + *
237 + * @param ptr thread data.
238 + */
239 +static void ebpf_mount_free(ebpf_module_t *em)
240 +{
241 + pthread_mutex_lock(&ebpf_exit_cleanup);
242 + if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) {
243 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
244 + pthread_mutex_unlock(&ebpf_exit_cleanup);
245 + return;
246 + }
247 + pthread_mutex_unlock(&ebpf_exit_cleanup);
248 +
249 + freez(mount_thread.thread);
250 + freez(mount_values);
251 +
252 +#ifdef LIBBPF_MAJOR_VERSION
253 + if (bpf_obj)
254 + mount_bpf__destroy(bpf_obj);
255 +#endif
256 +
257 + pthread_mutex_lock(&ebpf_exit_cleanup);
258 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
259 + pthread_mutex_unlock(&ebpf_exit_cleanup);
260 +}
261 +
262 /**
263 * Mount Exit
264 *
@@ -240,12 +269,8 @@ static inline int ebpf_mount_load_and_attach(struct mount_bpf *obj, ebpf_module_
269 static void ebpf_mount_exit(void *ptr)
270 {
271 ebpf_module_t *em = (ebpf_module_t *)ptr;
243 - if (!em->enabled) {
244 - em->enabled = NETDATA_MAIN_THREAD_EXITED;
245 - return;
246 - }
247 -
248 - ebpf_mount_exited = NETDATA_THREAD_EBPF_STOPPING;
272 + netdata_thread_cancel(*mount_thread.thread);
273 + ebpf_mount_free(em);
274 }
275
276 /**
@@ -258,19 +283,7 @@ static void ebpf_mount_exit(void *ptr)
283 static void ebpf_mount_cleanup(void *ptr)
284 {
285 ebpf_module_t *em = (ebpf_module_t *)ptr;
261 - if (ebpf_mount_exited != NETDATA_THREAD_EBPF_STOPPED)
262 - return;
263 -
264 - freez(mount_thread.thread);
265 - freez(mount_values);
266 -
267 -#ifdef LIBBPF_MAJOR_VERSION
268 - if (bpf_obj)
269 - mount_bpf__destroy(bpf_obj);
270 -#endif
271 -
272 - mount_thread.enabled = NETDATA_MAIN_THREAD_EXITED;
273 - em->enabled = NETDATA_MAIN_THREAD_EXITED;
286 + ebpf_mount_free(em);
287 }
288
289 /*****************************************************************
@@ -324,17 +337,12 @@ void *ebpf_mount_read_hash(void *ptr)
337
338 usec_t step = NETDATA_LATENCY_MOUNT_SLEEP_MS * em->update_every;
339 //This will be cancelled by its parent
327 - while (ebpf_mount_exited == NETDATA_THREAD_EBPF_RUNNING) {
328 - usec_t dt = heartbeat_next(&hb, step);
329 - (void)dt;
330 - if (ebpf_mount_exited == NETDATA_THREAD_EBPF_STOPPING)
331 - break;
340 + while (!ebpf_exit_plugin) {
341 + (void)heartbeat_next(&hb, step);
342
343 read_global_table();
344 }
345
336 - ebpf_mount_exited = NETDATA_THREAD_EBPF_STOPPED;
337 -
346 netdata_thread_cleanup_pop(1);
347 return NULL;
348 }
@@ -481,14 +489,11 @@ void *ebpf_mount_thread(void *ptr)
489 ebpf_module_t *em = (ebpf_module_t *)ptr;
490 em->maps = mount_maps;
491
484 - if (!em->enabled)
485 - goto endmount;
486 -
492 #ifdef LIBBPF_MAJOR_VERSION
493 ebpf_adjust_thread_load(em, default_btf);
494 #endif
495 if (ebpf_mount_load_bpf(em)) {
491 - em->enabled = CONFIG_BOOLEAN_NO;
496 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
497 goto endmount;
498 }
499
@@ -505,8 +510,7 @@ void *ebpf_mount_thread(void *ptr)
510 mount_collector(em);
511
512 endmount:
508 - if (!em->enabled)
509 - ebpf_update_disabled_plugin_stats(em);
513 + ebpf_update_disabled_plugin_stats(em);
514
515 netdata_thread_cleanup_pop(1);
516 return NULL;
collectors/ebpf.plugin/ebpf_oomkill.c
+9 -11
@@ -46,8 +46,7 @@ static netdata_publish_syscall_t oomkill_publish_aggregated = {.name = "oomkill"
46 static void oomkill_cleanup(void *ptr)
47 {
48 ebpf_module_t *em = (ebpf_module_t *)ptr;
49 -
50 - em->enabled = NETDATA_MAIN_THREAD_EXITED;
49 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
50 }
51
52 static void oomkill_write_data(int32_t *keys, uint32_t total)
@@ -362,29 +361,29 @@ void *ebpf_oomkill_thread(void *ptr)
361 if (unlikely(!all_pids || !em->apps_charts)) {
362 // When we are not running integration with apps, we won't fill necessary variables for this thread to run, so
363 // we need to disable it.
365 - if (em->enabled)
364 + if (em->thread->enabled)
365 info("%s apps integration is completely disabled.", NETDATA_DEFAULT_OOM_DISABLED_MSG);
366
368 - em->enabled = 0;
367 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
368 } else if (running_on_kernel < NETDATA_EBPF_KERNEL_4_14) {
370 - if (em->enabled)
369 + if (em->thread->enabled)
370 info("%s kernel does not have necessary tracepoints.", NETDATA_DEFAULT_OOM_DISABLED_MSG);
371
373 - em->enabled = 0;
372 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
373 }
374
376 - if (!em->enabled) {
375 + if (em->thread->enabled == NETDATA_THREAD_EBPF_STOPPED) {
376 goto endoomkill;
377 }
378
379 if (ebpf_enable_tracepoints(oomkill_tracepoints) == 0) {
381 - em->enabled = CONFIG_BOOLEAN_NO;
380 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
381 goto endoomkill;
382 }
383
384 em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
385 if (!em->probe_links) {
387 - em->enabled = CONFIG_BOOLEAN_NO;
386 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
387 goto endoomkill;
388 }
389
@@ -395,8 +394,7 @@ void *ebpf_oomkill_thread(void *ptr)
394 oomkill_collector(em);
395
396 endoomkill:
398 - if (!em->enabled)
399 - ebpf_update_disabled_plugin_stats(em);
397 + ebpf_update_disabled_plugin_stats(em);
398
399 netdata_thread_cleanup_pop(1);
400
collectors/ebpf.plugin/ebpf_process.c
+66 -101
@@ -54,21 +54,20 @@ struct config process_config = { .first_section = NULL,
54 .index = { .avl_tree = { .root = NULL, .compar = appconfig_section_compare },
55 .rwlock = AVL_LOCK_INITIALIZER } };
56
57 -static struct netdata_static_thread cgroup_thread = {
58 - .name = "EBPF CGROUP",
59 - .config_section = NULL,
60 - .config_name = NULL,
61 - .env_name = NULL,
62 - .enabled = 1,
63 - .thread = NULL,
64 - .init_routine = NULL,
65 - .start_routine = NULL
66 -};
67 -static enum ebpf_threads_status ebpf_process_exited = NETDATA_THREAD_EBPF_RUNNING;
68 -
57 static char *threads_stat[NETDATA_EBPF_THREAD_STAT_END] = {"total", "running"};
58 static char *load_event_stat[NETDATA_EBPF_LOAD_STAT_END] = {"legacy", "co-re"};
59
60 +static struct netdata_static_thread cgroup_thread = {
61 + .name = "EBPF CGROUP",
62 + .config_section = NULL,
63 + .config_name = NULL,
64 + .env_name = NULL,
65 + .enabled = 1,
66 + .thread = NULL,
67 + .init_routine = NULL,
68 + .start_routine = NULL
69 +};
70 +
71 /*****************************************************************
72 *
73 * PROCESS DATA AND SEND TO NETDATA
@@ -327,6 +326,55 @@ static void ebpf_process_update_apps_data()
326 }
327 }
328
329 +/**
330 + * Cgroup Exit
331 + *
332 + * Function used with netdata_thread_clean_push
333 + *
334 + * @param ptr unused argument
335 + */
336 +static void ebpf_cgroup_exit(void *ptr)
337 +{
338 + UNUSED(ptr);
339 +}
340 +
341 +/**
342 + * Cgroup update shm
343 + *
344 + * This is the thread callback.
345 + * This thread is necessary, because we cannot freeze the whole plugin to read the data from shared memory.
346 + *
347 + * @param ptr It is a NULL value for this thread.
348 + *
349 + * @return It always returns NULL.
350 + */
351 +void *ebpf_cgroup_update_shm(void *ptr)
352 +{
353 + netdata_thread_cleanup_push(ebpf_cgroup_exit, ptr);
354 + heartbeat_t hb;
355 + heartbeat_init(&hb);
356 +
357 + usec_t step = 3 * USEC_PER_SEC;
358 + int counter = NETDATA_EBPF_CGROUP_UPDATE - 1;
359 + //This will be cancelled by its parent
360 + while (!ebpf_exit_plugin) {
361 + (void)heartbeat_next(&hb, step);
362 +
363 + // We are using a small heartbeat time to wake up thread,
364 + // but we should not update so frequently the shared memory data
365 + if (++counter >= NETDATA_EBPF_CGROUP_UPDATE) {
366 + counter = 0;
367 + if (!shm_ebpf_cgroup.header)
368 + ebpf_map_cgroup_shared_memory();
369 +
370 + ebpf_parse_cgroup_shm_data();
371 + }
372 + }
373 +
374 + netdata_thread_cleanup_pop(1);
375 + return NULL;
376 +}
377 +
378 /**
379 * Update cgroup
380 *
@@ -686,32 +734,18 @@ static void ebpf_process_disable_tracepoints()
734 * @param ptr thread data.
735 */
736 static void ebpf_process_exit(void *ptr)
689 -{
690 - (void)ptr;
691 - ebpf_process_exited = NETDATA_THREAD_EBPF_STOPPING;
692 -}
693 -
694 -/**
695 - * Process cleanup
696 - *
697 - * Cleanup allocated memory.
698 - *
699 - * @param ptr thread data.
700 - */
701 -static void ebpf_process_cleanup(void *ptr)
737 {
738 ebpf_module_t *em = (ebpf_module_t *)ptr;
704 - if (ebpf_process_exited != NETDATA_THREAD_EBPF_STOPPED)
705 - return;
739
740 ebpf_cleanup_publish_syscall(process_publish_aggregated);
741 freez(process_hash_values);
709 - freez(cgroup_thread.thread);
742
743 ebpf_process_disable_tracepoints();
744
713 - cgroup_thread.enabled = NETDATA_MAIN_THREAD_EXITED;
714 - em->enabled = NETDATA_MAIN_THREAD_EXITED;
745 + pthread_mutex_lock(&ebpf_exit_cleanup);
746 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
747 + pthread_mutex_unlock(&ebpf_exit_cleanup);
748 + pthread_cancel(*cgroup_thread.thread);
749 }
750
751 /*****************************************************************
@@ -720,47 +754,6 @@ static void ebpf_process_cleanup(void *ptr)
754 *
755 *****************************************************************/
756
723 -/**
724 - * Cgroup update shm
725 - *
726 - * This is the thread callback.
727 - * This thread is necessary, because we cannot freeze the whole plugin to read the data from shared memory.
728 - *
729 - * @param ptr It is a NULL value for this thread.
730 - *
731 - * @return It always returns NULL.
732 - */
733 -void *ebpf_cgroup_update_shm(void *ptr)
734 -{
735 - netdata_thread_cleanup_push(ebpf_process_cleanup, ptr);
736 - heartbeat_t hb;
737 - heartbeat_init(&hb);
738 -
739 - usec_t step = 3 * USEC_PER_SEC;
740 - int counter = NETDATA_EBPF_CGROUP_UPDATE - 1;
741 - //This will be cancelled by its parent
742 - while (ebpf_process_exited == NETDATA_THREAD_EBPF_RUNNING) {
743 - usec_t dt = heartbeat_next(&hb, step);
744 - (void)dt;
745 - if (ebpf_process_exited == NETDATA_THREAD_EBPF_STOPPING)
746 - break;
747 -
748 - // We are using a small heartbeat time to wake up thread,
749 - // but we should not update so frequently the shared memory data
750 - if (++counter >= NETDATA_EBPF_CGROUP_UPDATE) {
751 - counter = 0;
752 - if (!shm_ebpf_cgroup.header)
753 - ebpf_map_cgroup_shared_memory();
754 -
755 - ebpf_parse_cgroup_shm_data();
756 - }
757 - }
758 -
759 - ebpf_process_exited = NETDATA_THREAD_EBPF_STOPPED;
760 -
761 - netdata_thread_cleanup_pop(1);
762 - return NULL;
763 -}
757
758 /**
759 * Sum PIDs
@@ -1111,11 +1104,12 @@ void ebpf_send_statistic_data()
1104 */
1105 static void process_collector(ebpf_module_t *em)
1106 {
1107 + // Start cgroup integration before other threads
1108 cgroup_thread.thread = mallocz(sizeof(netdata_thread_t));
1109 cgroup_thread.start_routine = ebpf_cgroup_update_shm;
1110
1111 netdata_thread_create(cgroup_thread.thread, cgroup_thread.name, NETDATA_THREAD_OPTION_DEFAULT,
1118 - ebpf_cgroup_update_shm, em);
1112 + ebpf_cgroup_update_shm, NULL);
1113
1114 heartbeat_t hb;
1115 heartbeat_init(&hb);
@@ -1232,34 +1226,6 @@ static void set_local_pointers()
1226 *
1227 *****************************************************************/
1228
1235 -/**
1236 - *
1237 - */
1238 -static void wait_for_all_threads_die()
1239 -{
1240 - ebpf_modules[EBPF_MODULE_PROCESS_IDX].enabled = 0;
1241 -
1242 - heartbeat_t hb;
1243 - heartbeat_init(&hb);
1244 -
1245 - int max = 10;
1246 - int i;
1247 - for (i = 0; i < max; i++) {
1248 - heartbeat_next(&hb, 200000);
1249 -
1250 - size_t j, counter = 0, compare = 0;
1251 - for (j = 0; ebpf_modules[j].thread_name; j++) {
1252 - if (!ebpf_modules[j].enabled)
1253 - counter++;
1254 -
1255 - compare++;
1256 - }
1257 -
1258 - if (counter == compare)
1259 - break;
1260 - }
1261 -}
1262 -
1229 /**
1230 * Enable tracepoints
1231 *
@@ -1356,7 +1322,6 @@ endprocess:
1322 if (!em->enabled)
1323 ebpf_update_disabled_plugin_stats(em);
1324
1359 - wait_for_all_threads_die();
1325 netdata_thread_cleanup_pop(1);
1326 return NULL;
1327 }
collectors/ebpf.plugin/ebpf_shm.c
+37 -36
@@ -44,7 +44,6 @@ struct netdata_static_thread shm_threads = {
44 .init_routine = NULL,
45 .start_routine = NULL
46 };
47 -static enum ebpf_threads_status ebpf_shm_exited = NETDATA_THREAD_EBPF_RUNNING;
47
48 netdata_ebpf_targets_t shm_targets[] = { {.name = "shmget", .mode = EBPF_LOAD_TRAMPOLINE},
49 {.name = "shmat", .mode = EBPF_LOAD_TRAMPOLINE},
@@ -290,6 +289,36 @@ static inline int ebpf_shm_load_and_attach(struct shm_bpf *obj, ebpf_module_t *e
289 * FUNCTIONS TO CLOSE THE THREAD
290 *****************************************************************/
291
292 +/**
293 + * SHM Free
294 + *
295 + * Cleanup variables after child threads to stop
296 + *
297 + * @param ptr thread data.
298 + */
299 +static void ebpf_shm_free(ebpf_module_t *em)
300 +{
301 + pthread_mutex_lock(&ebpf_exit_cleanup);
302 + if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) {
303 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
304 + pthread_mutex_unlock(&ebpf_exit_cleanup);
305 + return;
306 + }
307 + pthread_mutex_unlock(&ebpf_exit_cleanup);
308 +
309 + ebpf_cleanup_publish_syscall(shm_publish_aggregated);
310 +
311 + freez(shm_vector);
312 + freez(shm_values);
313 +
314 +#ifdef LIBBPF_MAJOR_VERSION
315 + if (bpf_obj)
316 + shm_bpf__destroy(bpf_obj);
317 +#endif
318 +
319 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
320 +}
321 +
322 /**
323 * SHM Exit
324 *
@@ -300,12 +329,8 @@ static inline int ebpf_shm_load_and_attach(struct shm_bpf *obj, ebpf_module_t *e
329 static void ebpf_shm_exit(void *ptr)
330 {
331 ebpf_module_t *em = (ebpf_module_t *)ptr;
303 - if (!em->enabled) {
304 - em->enabled = NETDATA_MAIN_THREAD_EXITED;
305 - return;
306 - }
307 -
308 - ebpf_shm_exited = NETDATA_THREAD_EBPF_STOPPING;
332 + netdata_thread_cancel(*shm_threads.thread);
333 + ebpf_shm_free(em);
334 }
335
336 /**
@@ -318,21 +343,7 @@ static void ebpf_shm_exit(void *ptr)
343 static void ebpf_shm_cleanup(void *ptr)
344 {
345 ebpf_module_t *em = (ebpf_module_t *)ptr;
321 - if (ebpf_shm_exited != NETDATA_THREAD_EBPF_STOPPED)
322 - return;
323 -
324 - ebpf_cleanup_publish_syscall(shm_publish_aggregated);
325 -
326 - freez(shm_vector);
327 - freez(shm_values);
328 -
329 -#ifdef LIBBPF_MAJOR_VERSION
330 - if (bpf_obj)
331 - shm_bpf__destroy(bpf_obj);
332 -#endif
333 -
334 - shm_threads.enabled = NETDATA_MAIN_THREAD_EXITED;
335 - em->enabled = NETDATA_MAIN_THREAD_EXITED;
346 + ebpf_shm_free(em);
347 }
348
349 /*****************************************************************
@@ -514,17 +525,12 @@ void *ebpf_shm_read_hash(void *ptr)
525
526 ebpf_module_t *em = (ebpf_module_t *)ptr;
527 usec_t step = NETDATA_SHM_SLEEP_MS * em->update_every;
517 - while (ebpf_shm_exited == NETDATA_THREAD_EBPF_RUNNING) {
518 - usec_t dt = heartbeat_next(&hb, step);
519 - (void)dt;
520 - if (ebpf_shm_exited == NETDATA_THREAD_EBPF_STOPPING)
521 - break;
528 + while (!ebpf_exit_plugin) {
529 + (void)heartbeat_next(&hb, step);
530
531 read_global_table();
532 }
533
526 - ebpf_shm_exited = NETDATA_THREAD_EBPF_STOPPED;
527 -
534 netdata_thread_cleanup_pop(1);
535 return NULL;
536 }
@@ -1091,15 +1097,11 @@ void *ebpf_shm_thread(void *ptr)
1097
1098 ebpf_update_pid_table(&shm_maps[NETDATA_PID_SHM_TABLE], em);
1099
1094 - if (!em->enabled) {
1095 - goto endshm;
1096 - }
1097 -
1100 #ifdef LIBBPF_MAJOR_VERSION
1101 ebpf_adjust_thread_load(em, default_btf);
1102 #endif
1103 if (ebpf_shm_load_bpf(em)) {
1102 - em->enabled = CONFIG_BOOLEAN_NO;
1104 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
1105 goto endshm;
1106 }
1107
@@ -1128,8 +1130,7 @@ void *ebpf_shm_thread(void *ptr)
1130 shm_collector(em);
1131
1132 endshm:
1131 - if (!em->enabled)
1132 - ebpf_update_disabled_plugin_stats(em);
1133 + ebpf_update_disabled_plugin_stats(em);
1134
1135 netdata_thread_cleanup_pop(1);
1136 return NULL;
collectors/ebpf.plugin/ebpf_socket.c
+43 -38
@@ -97,7 +97,6 @@ struct netdata_static_thread socket_threads = {
97 .init_routine = NULL,
98 .start_routine = NULL
99 };
100 -static enum ebpf_threads_status ebpf_socket_exited = NETDATA_THREAD_EBPF_RUNNING;
100
101 #ifdef LIBBPF_MAJOR_VERSION
102 #include "includes/socket.skel.h" // BTF code
@@ -588,35 +587,21 @@ static void clean_ip_structure(ebpf_network_viewer_ip_list_t **clean)
587 }
588
589 /**
591 - * Socket exit
590 + * Socket Free
591 *
593 - * Clean up the main thread.
592 + * Cleanup variables after child threads to stop
593 *
594 * @param ptr thread data.
595 */
597 -static void ebpf_socket_exit(void *ptr)
596 +static void ebpf_socket_free(ebpf_module_t *em )
597 {
599 - ebpf_module_t *em = (ebpf_module_t *)ptr;
600 - if (!em->enabled) {
601 - em->enabled = NETDATA_MAIN_THREAD_EXITED;
598 + pthread_mutex_lock(&ebpf_exit_cleanup);
599 + if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) {
600 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
601 + pthread_mutex_unlock(&ebpf_exit_cleanup);
602 return;
603 }
604 -
605 - ebpf_socket_exited = NETDATA_THREAD_EBPF_STOPPING;
606 -}
607 -
608 -/**
609 - * Socket cleanup
610 - *
611 - * Clean up allocated addresses.
612 - *
613 - * @param ptr thread data.
614 - */
615 -void ebpf_socket_cleanup(void *ptr)
616 -{
617 - ebpf_module_t *em = (ebpf_module_t *)ptr;
618 - if (ebpf_socket_exited != NETDATA_THREAD_EBPF_STOPPED)
619 - return;
604 + pthread_mutex_unlock(&ebpf_exit_cleanup);
605
606 ebpf_cleanup_publish_syscall(socket_publish_aggregated);
607 freez(socket_hash_values);
@@ -646,8 +631,37 @@ void ebpf_socket_cleanup(void *ptr)
631 if (bpf_obj)
632 socket_bpf__destroy(bpf_obj);
633 #endif
649 - socket_threads.enabled = NETDATA_MAIN_THREAD_EXITED;
650 - em->enabled = NETDATA_MAIN_THREAD_EXITED;
634 +
635 + pthread_mutex_lock(&ebpf_exit_cleanup);
636 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
637 + pthread_mutex_unlock(&ebpf_exit_cleanup);
638 +}
639 +
640 +/**
641 + * Socket exit
642 + *
643 + * Clean up the main thread.
644 + *
645 + * @param ptr thread data.
646 + */
647 +static void ebpf_socket_exit(void *ptr)
648 +{
649 + ebpf_module_t *em = (ebpf_module_t *)ptr;
650 + netdata_thread_cancel(*socket_threads.thread);
651 + ebpf_socket_free(em);
652 +}
653 +
654 +/**
655 + * Socket cleanup
656 + *
657 + * Clean up allocated addresses.
658 + *
659 + * @param ptr thread data.
660 + */
661 +void ebpf_socket_cleanup(void *ptr)
662 +{
663 + ebpf_module_t *em = (ebpf_module_t *)ptr;
664 + ebpf_socket_free(em);
665 }
666
667 /*****************************************************************
@@ -2153,11 +2167,8 @@ void *ebpf_socket_read_hash(void *ptr)
2167 int fd_ipv4 = socket_maps[NETDATA_SOCKET_TABLE_IPV4].map_fd;
2168 int fd_ipv6 = socket_maps[NETDATA_SOCKET_TABLE_IPV6].map_fd;
2169 int network_connection = em->optional;
2156 - while (ebpf_socket_exited == NETDATA_THREAD_EBPF_RUNNING) {
2157 - usec_t dt = heartbeat_next(&hb, step);
2158 - (void)dt;
2159 - if (ebpf_socket_exited == NETDATA_THREAD_EBPF_STOPPING)
2160 - break;
2170 + while (!ebpf_exit_plugin) {
2171 + (void)heartbeat_next(&hb, step);
2172
2173 pthread_mutex_lock(&nv_mutex);
2174 read_listen_table();
@@ -2167,8 +2178,6 @@ void *ebpf_socket_read_hash(void *ptr)
2178 pthread_mutex_unlock(&nv_mutex);
2179 }
2180
2170 - ebpf_socket_exited = NETDATA_THREAD_EBPF_STOPPED;
2171 -
2181 netdata_thread_cleanup_pop(1);
2182 return NULL;
2183 }
@@ -3919,11 +3928,8 @@ void *ebpf_socket_thread(void *ptr)
3928 parse_service_name_section(&socket_config);
3929 parse_table_size_options(&socket_config);
3930
3922 - if (!em->enabled)
3923 - goto endsocket;
3924 -
3931 if (pthread_mutex_init(&nv_mutex, NULL)) {
3926 - em->enabled = CONFIG_BOOLEAN_NO;
3932 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
3933 error("Cannot initialize local mutex");
3934 goto endsocket;
3935 }
@@ -3963,8 +3969,7 @@ void *ebpf_socket_thread(void *ptr)
3969 socket_collector((usec_t)(em->update_every * USEC_PER_SEC), em);
3970
3971 endsocket:
3966 - if (!em->enabled)
3967 - ebpf_update_disabled_plugin_stats(em);
3972 + ebpf_update_disabled_plugin_stats(em);
3973
3974 netdata_thread_cleanup_pop(1);
3975 return NULL;
collectors/ebpf.plugin/ebpf_softirq.c
+37 -33
@@ -64,7 +64,35 @@ static struct netdata_static_thread softirq_threads = {
64 .init_routine = NULL,
65 .start_routine = NULL
66 };
67 -static enum ebpf_threads_status ebpf_softirq_exited = NETDATA_THREAD_EBPF_RUNNING;
67 +
68 +/**
69 + * Cachestat Free
70 + *
71 + * Cleanup variables after child threads to stop
72 + *
73 + * @param ptr thread data.
74 + */
75 +static void ebpf_softirq_free(ebpf_module_t *em)
76 +{
77 + pthread_mutex_lock(&ebpf_exit_cleanup);
78 + if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) {
79 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
80 + pthread_mutex_unlock(&ebpf_exit_cleanup);
81 + return;
82 + }
83 + pthread_mutex_unlock(&ebpf_exit_cleanup);
84 +
85 + freez(softirq_threads.thread);
86 +
87 + for (int i = 0; softirq_tracepoints[i].class != NULL; i++) {
88 + ebpf_disable_tracepoint(&softirq_tracepoints[i]);
89 + }
90 + freez(softirq_ebpf_vals);
91 +
92 + pthread_mutex_lock(&ebpf_exit_cleanup);
93 + em->thread->enabled = NETDATA_MAIN_THREAD_EXITED;
94 + pthread_mutex_unlock(&ebpf_exit_cleanup);
95 +}
96
97 /**
98 * Exit
@@ -76,12 +104,8 @@ static enum ebpf_threads_status ebpf_softirq_exited = NETDATA_THREAD_EBPF_RUNNIN
104 static void softirq_exit(void *ptr)
105 {
106 ebpf_module_t *em = (ebpf_module_t *)ptr;
79 - if (!em->enabled) {
80 - em->enabled = NETDATA_MAIN_THREAD_EXITED;
81 - return;
82 - }
83 -
84 - ebpf_softirq_exited = NETDATA_THREAD_EBPF_STOPPING;
107 + netdata_thread_cancel(*softirq_threads.thread);
108 + ebpf_softirq_free(em);
109 }
110
111 /**
@@ -94,18 +118,7 @@ static void softirq_exit(void *ptr)
118 static void softirq_cleanup(void *ptr)
119 {
120 ebpf_module_t *em = (ebpf_module_t *)ptr;
97 - if (ebpf_softirq_exited != NETDATA_THREAD_EBPF_STOPPED)
98 - return;
99 -
100 - freez(softirq_threads.thread);
101 -
102 - for (int i = 0; softirq_tracepoints[i].class != NULL; i++) {
103 - ebpf_disable_tracepoint(&softirq_tracepoints[i]);
104 - }
105 - freez(softirq_ebpf_vals);
106 -
107 - softirq_threads.enabled = NETDATA_MAIN_THREAD_EXITED;
108 - em->enabled = NETDATA_MAIN_THREAD_EXITED;
121 + ebpf_softirq_free(em);
122 }
123
124 /*****************************************************************
@@ -145,15 +158,11 @@ static void *softirq_reader(void *ptr)
158 ebpf_module_t *em = (ebpf_module_t *)ptr;
159
160 usec_t step = NETDATA_SOFTIRQ_SLEEP_MS * em->update_every;
148 - while (ebpf_softirq_exited == NETDATA_THREAD_EBPF_RUNNING) {
149 - usec_t dt = heartbeat_next(&hb, step);
150 - UNUSED(dt);
151 - if (ebpf_softirq_exited == NETDATA_THREAD_EBPF_STOPPING)
152 - break;
161 + while (!ebpf_exit_plugin) {
162 + (void)heartbeat_next(&hb, step);
163
164 softirq_read_latency_map();
165 }
156 - ebpf_softirq_exited = NETDATA_THREAD_EBPF_STOPPED;
166
167 netdata_thread_cleanup_pop(1);
168 return NULL;
@@ -259,26 +268,21 @@ void *ebpf_softirq_thread(void *ptr)
268 ebpf_module_t *em = (ebpf_module_t *)ptr;
269 em->maps = softirq_maps;
270
262 - if (!em->enabled) {
263 - goto endsoftirq;
264 - }
265 -
271 if (ebpf_enable_tracepoints(softirq_tracepoints) == 0) {
267 - em->enabled = CONFIG_BOOLEAN_NO;
272 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
273 goto endsoftirq;
274 }
275
276 em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
277 if (!em->probe_links) {
273 - em->enabled = CONFIG_BOOLEAN_NO;
278 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
279 goto endsoftirq;
280 }
281
282 softirq_collector(em);
283
284 endsoftirq:
280 - if (!em->enabled)
281 - ebpf_update_disabled_plugin_stats(em);
285 + ebpf_update_disabled_plugin_stats(em);
286
287 netdata_thread_cleanup_pop(1);
288
collectors/ebpf.plugin/ebpf_swap.c
+39 -35
@@ -44,7 +44,6 @@ struct netdata_static_thread swap_threads = {
44 .init_routine = NULL,
45 .start_routine = NULL
46 };
47 -static enum ebpf_threads_status ebpf_swap_exited = NETDATA_THREAD_EBPF_RUNNING;
47
48 netdata_ebpf_targets_t swap_targets[] = { {.name = "swap_readpage", .mode = EBPF_LOAD_TRAMPOLINE},
49 {.name = "swap_writepage", .mode = EBPF_LOAD_TRAMPOLINE},
@@ -227,6 +226,38 @@ static inline int ebpf_swap_load_and_attach(struct swap_bpf *obj, ebpf_module_t
226 *
227 *****************************************************************/
228
229 +/**
230 + * Cachestat Free
231 + *
232 + * Cleanup variables after child threads to stop
233 + *
234 + * @param ptr thread data.
235 + */
236 +static void ebpf_swap_free(ebpf_module_t *em)
237 +{
238 + pthread_mutex_lock(&ebpf_exit_cleanup);
239 + if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) {
240 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
241 + pthread_mutex_unlock(&ebpf_exit_cleanup);
242 + return;
243 + }
244 + pthread_mutex_unlock(&ebpf_exit_cleanup);
245 +
246 + ebpf_cleanup_publish_syscall(swap_publish_aggregated);
247 +
248 + freez(swap_vector);
249 + freez(swap_values);
250 + freez(swap_threads.thread);
251 +
252 +#ifdef LIBBPF_MAJOR_VERSION
253 + if (bpf_obj)
254 + swap_bpf__destroy(bpf_obj);
255 +#endif
256 + pthread_mutex_lock(&ebpf_exit_cleanup);
257 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
258 + pthread_mutex_unlock(&ebpf_exit_cleanup);
259 +}
260 +
261 /**
262 * Swap exit
263 *
@@ -237,12 +268,8 @@ static inline int ebpf_swap_load_and_attach(struct swap_bpf *obj, ebpf_module_t
268 static void ebpf_swap_exit(void *ptr)
269 {
270 ebpf_module_t *em = (ebpf_module_t *)ptr;
240 - if (!em->enabled) {
241 - em->enabled = NETDATA_MAIN_THREAD_EXITED;
242 - return;
243 - }
244 -
245 - ebpf_swap_exited = NETDATA_THREAD_EBPF_STOPPING;
271 + netdata_thread_cancel(*swap_threads.thread);
272 + ebpf_swap_free(em);
273 }
274
275 /**
@@ -255,21 +282,7 @@ static void ebpf_swap_exit(void *ptr)
282 static void ebpf_swap_cleanup(void *ptr)
283 {
284 ebpf_module_t *em = (ebpf_module_t *)ptr;
258 - if (ebpf_swap_exited != NETDATA_THREAD_EBPF_STOPPED)
259 - return;
260 -
261 - ebpf_cleanup_publish_syscall(swap_publish_aggregated);
262 -
263 - freez(swap_vector);
264 - freez(swap_values);
265 - freez(swap_threads.thread);
266 -
267 -#ifdef LIBBPF_MAJOR_VERSION
268 - if (bpf_obj)
269 - swap_bpf__destroy(bpf_obj);
270 -#endif
271 - swap_threads.enabled = NETDATA_MAIN_THREAD_EXITED;
272 - em->enabled = NETDATA_MAIN_THREAD_EXITED;
285 + ebpf_swap_free(em);
286 }
287
288 /*****************************************************************
@@ -436,17 +449,12 @@ void *ebpf_swap_read_hash(void *ptr)
449
450 ebpf_module_t *em = (ebpf_module_t *)ptr;
451 usec_t step = NETDATA_SWAP_SLEEP_MS * em->update_every;
439 - while (ebpf_swap_exited == NETDATA_THREAD_EBPF_RUNNING) {
440 - usec_t dt = heartbeat_next(&hb, step);
441 - (void)dt;
442 - if (ebpf_swap_exited == NETDATA_THREAD_EBPF_STOPPING)
443 - break;
452 + while (!ebpf_exit_plugin) {
453 + (void)heartbeat_next(&hb, step);
454
455 read_global_table();
456 }
457
448 - ebpf_swap_exited = NETDATA_THREAD_EBPF_STOPPED;
449 -
458 netdata_thread_cleanup_pop(1);
459 return NULL;
460 }
@@ -878,14 +886,11 @@ void *ebpf_swap_thread(void *ptr)
886
887 ebpf_update_pid_table(&swap_maps[NETDATA_PID_SWAP_TABLE], em);
888
881 - if (!em->enabled)
882 - goto endswap;
883 -
889 #ifdef LIBBPF_MAJOR_VERSION
890 ebpf_adjust_thread_load(em, default_btf);
891 #endif
892 if (ebpf_swap_load_bpf(em)) {
888 - em->enabled = CONFIG_BOOLEAN_NO;
893 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
894 goto endswap;
895 }
896
@@ -903,8 +908,7 @@ void *ebpf_swap_thread(void *ptr)
908 swap_collector(em);
909
910 endswap:
906 - if (!em->enabled)
907 - ebpf_update_disabled_plugin_stats(em);
911 + ebpf_update_disabled_plugin_stats(em);
912
913 netdata_thread_cleanup_pop(1);
914 return NULL;
collectors/ebpf.plugin/ebpf_sync.c
+36 -42
@@ -56,8 +56,6 @@ netdata_ebpf_targets_t sync_targets[] = { {.name = NETDATA_SYSCALLS_SYNC, .mode
56 {.name = NETDATA_SYSCALLS_FDATASYNC, .mode = EBPF_LOAD_TRAMPOLINE},
57 {.name = NETDATA_SYSCALLS_SYNC_FILE_RANGE, .mode = EBPF_LOAD_TRAMPOLINE},
58 {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
59 -static enum ebpf_threads_status ebpf_sync_exited = NETDATA_THREAD_EBPF_RUNNING;
60 -
59
60 #ifdef LIBBPF_MAJOR_VERSION
61 /*****************************************************************
@@ -191,6 +189,7 @@ static inline int ebpf_sync_load_and_attach(struct sync_bpf *obj, ebpf_module_t
189 *
190 *****************************************************************/
191
192 +#ifdef LIBBPF_MAJOR_VERSION
193 /**
194 * Cleanup Objects
195 *
@@ -201,22 +200,37 @@ void ebpf_sync_cleanup_objects()
200 int i;
201 for (i = 0; local_syscalls[i].syscall; i++) {
202 ebpf_sync_syscalls_t *w = &local_syscalls[i];
204 - if (w->probe_links) {
205 - struct bpf_program *prog;
206 - size_t j = 0 ;
207 - bpf_object__for_each_program(prog, w->objects) {
208 - bpf_link__destroy(w->probe_links[j]);
209 - j++;
210 - }
211 - freez(w->probe_links);
212 - if (w->objects)
213 - bpf_object__close(w->objects);
214 - }
215 -#ifdef LIBBPF_MAJOR_VERSION
216 - else if (w->sync_obj)
203 + if (w->sync_obj)
204 sync_bpf__destroy(w->sync_obj);
205 + }
206 +}
207 #endif
208 +
209 +/**
210 + * Sync Free
211 + *
212 + * Cleanup variables after child threads to stop
213 + *
214 + * @param ptr thread data.
215 + */
216 +static void ebpf_sync_free(ebpf_module_t *em)
217 +{
218 + pthread_mutex_lock(&ebpf_exit_cleanup);
219 + if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) {
220 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
221 + pthread_mutex_unlock(&ebpf_exit_cleanup);
222 + return;
223 }
224 + pthread_mutex_unlock(&ebpf_exit_cleanup);
225 +
226 +#ifdef LIBBPF_MAJOR_VERSION
227 + ebpf_sync_cleanup_objects();
228 +#endif
229 + freez(sync_threads.thread);
230 +
231 + pthread_mutex_lock(&ebpf_exit_cleanup);
232 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
233 + pthread_mutex_unlock(&ebpf_exit_cleanup);
234 }
235
236 /**
@@ -229,12 +243,8 @@ void ebpf_sync_cleanup_objects()
243 static void ebpf_sync_exit(void *ptr)
244 {
245 ebpf_module_t *em = (ebpf_module_t *)ptr;
232 - if (!em->enabled) {
233 - em->enabled = NETDATA_MAIN_THREAD_EXITED;
234 - return;
235 - }
236 -
237 - ebpf_sync_exited = NETDATA_THREAD_EBPF_STOPPING;
246 + netdata_thread_cancel(*sync_threads.thread);
247 + ebpf_sync_free(em);
248 }
249
250 /**
@@ -245,14 +255,7 @@ static void ebpf_sync_exit(void *ptr)
255 static void ebpf_sync_cleanup(void *ptr)
256 {
257 ebpf_module_t *em = (ebpf_module_t *)ptr;
248 - if (ebpf_sync_exited != NETDATA_THREAD_EBPF_STOPPED)
249 - return;
250 -
251 - ebpf_sync_cleanup_objects();
252 - freez(sync_threads.thread);
253 -
254 - sync_threads.enabled = NETDATA_MAIN_THREAD_EXITED;
255 - em->enabled = NETDATA_MAIN_THREAD_EXITED;
258 + ebpf_sync_free(em);
259 }
260
261 /*****************************************************************
@@ -380,17 +383,12 @@ void *ebpf_sync_read_hash(void *ptr)
383 heartbeat_init(&hb);
384 usec_t step = NETDATA_EBPF_SYNC_SLEEP_MS * em->update_every;
385
383 - while (ebpf_sync_exited == NETDATA_THREAD_EBPF_RUNNING) {
384 - usec_t dt = heartbeat_next(&hb, step);
385 - (void)dt;
386 - if (ebpf_sync_exited == NETDATA_THREAD_EBPF_STOPPING)
387 - break;
386 + while (!ebpf_exit_plugin) {
387 + (void)heartbeat_next(&hb, step);
388
389 read_global_table();
390 }
391
392 - ebpf_sync_exited = NETDATA_THREAD_EBPF_STOPPED;
393 -
392 netdata_thread_cleanup_pop(1);
393 return NULL;
394 }
@@ -580,14 +578,11 @@ void *ebpf_sync_thread(void *ptr)
578
579 ebpf_sync_parse_syscalls();
580
583 - if (!em->enabled)
584 - goto endsync;
585 -
581 #ifdef LIBBPF_MAJOR_VERSION
582 ebpf_adjust_thread_load(em, default_btf);
583 #endif
584 if (ebpf_sync_initialize_syscall(em)) {
590 - em->enabled = CONFIG_BOOLEAN_NO;
585 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
586 goto endsync;
587 }
588
@@ -606,8 +601,7 @@ void *ebpf_sync_thread(void *ptr)
601 sync_collector(em);
602
603 endsync:
609 - if (!em->enabled)
610 - ebpf_update_disabled_plugin_stats(em);
604 + ebpf_update_disabled_plugin_stats(em);
605
606 netdata_thread_cleanup_pop(1);
607 return NULL;
collectors/ebpf.plugin/ebpf_vfs.c
+39 -34
@@ -44,7 +44,6 @@ struct netdata_static_thread vfs_threads = {
44 .init_routine = NULL,
45 .start_routine = NULL
46 };
47 -static enum ebpf_threads_status ebpf_vfs_exited = NETDATA_THREAD_EBPF_RUNNING;
47
48 netdata_ebpf_targets_t vfs_targets[] = { {.name = "vfs_write", .mode = EBPF_LOAD_TRAMPOLINE},
49 {.name = "vfs_writev", .mode = EBPF_LOAD_TRAMPOLINE},
@@ -399,6 +398,38 @@ static inline int ebpf_vfs_load_and_attach(struct vfs_bpf *obj, ebpf_module_t *e
398 * FUNCTIONS TO CLOSE THE THREAD
399 *
400 *****************************************************************/
401 +
402 +/**
403 + * Cachestat Free
404 + *
405 + * Cleanup variables after child threads to stop
406 + *
407 + * @param ptr thread data.
408 + */
409 +static void ebpf_vfs_free(ebpf_module_t *em)
410 +{
411 + pthread_mutex_lock(&ebpf_exit_cleanup);
412 + if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) {
413 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
414 + pthread_mutex_unlock(&ebpf_exit_cleanup);
415 + return;
416 + }
417 + pthread_mutex_unlock(&ebpf_exit_cleanup);
418 +
419 + freez(vfs_hash_values);
420 + freez(vfs_vector);
421 + freez(vfs_threads.thread);
422 +
423 +#ifdef LIBBPF_MAJOR_VERSION
424 + if (bpf_obj)
425 + vfs_bpf__destroy(bpf_obj);
426 +#endif
427 +
428 + pthread_mutex_lock(&ebpf_exit_cleanup);
429 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
430 + pthread_mutex_unlock(&ebpf_exit_cleanup);
431 +}
432 +
433 /**
434 * Exit
435 *
@@ -409,12 +440,8 @@ static inline int ebpf_vfs_load_and_attach(struct vfs_bpf *obj, ebpf_module_t *e
440 static void ebpf_vfs_exit(void *ptr)
441 {
442 ebpf_module_t *em = (ebpf_module_t *)ptr;
412 - if (!em->enabled) {
413 - em->enabled = NETDATA_MAIN_THREAD_EXITED;
414 - return;
415 - }
416 -
417 - ebpf_vfs_exited = NETDATA_THREAD_EBPF_STOPPING;
443 + netdata_thread_cancel(*vfs_threads.thread);
444 + ebpf_vfs_free(em);
445 }
446
447 /**
@@ -425,20 +452,7 @@ static void ebpf_vfs_exit(void *ptr)
452 static void ebpf_vfs_cleanup(void *ptr)
453 {
454 ebpf_module_t *em = (ebpf_module_t *)ptr;
428 - if (ebpf_vfs_exited != NETDATA_THREAD_EBPF_STOPPED)
429 - return;
430 -
431 - freez(vfs_hash_values);
432 - freez(vfs_vector);
433 - freez(vfs_threads.thread);
434 -
435 -#ifdef LIBBPF_MAJOR_VERSION
436 - if (bpf_obj)
437 - vfs_bpf__destroy(bpf_obj);
438 -#endif
439 -
440 - vfs_threads.enabled = NETDATA_MAIN_THREAD_EXITED;
441 - em->enabled = NETDATA_MAIN_THREAD_EXITED;
455 + ebpf_vfs_free(em);
456 }
457
458 /*****************************************************************
@@ -879,17 +893,12 @@ void *ebpf_vfs_read_hash(void *ptr)
893
894 usec_t step = NETDATA_LATENCY_VFS_SLEEP_MS * em->update_every;
895 //This will be cancelled by its parent
882 - while (ebpf_vfs_exited == NETDATA_THREAD_EBPF_RUNNING) {
883 - usec_t dt = heartbeat_next(&hb, step);
884 - (void)dt;
885 - if (ebpf_vfs_exited == NETDATA_THREAD_EBPF_STOPPING)
886 - break;
896 + while (!ebpf_exit_plugin) {
897 + (void)heartbeat_next(&hb, step);
898
899 read_global_table();
900 }
901
891 - ebpf_vfs_exited = NETDATA_THREAD_EBPF_STOPPED;
892 -
902 netdata_thread_cleanup_pop(1);
903 return NULL;
904 }
@@ -1943,14 +1952,11 @@ void *ebpf_vfs_thread(void *ptr)
1952
1953 ebpf_vfs_allocate_global_vectors(em->apps_charts);
1954
1946 - if (!em->enabled)
1947 - goto endvfs;
1948 -
1955 #ifdef LIBBPF_MAJOR_VERSION
1956 ebpf_adjust_thread_load(em, default_btf);
1957 #endif
1958 if (ebpf_vfs_load_bpf(em)) {
1953 - em->enabled = CONFIG_BOOLEAN_NO;
1959 + em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
1960 goto endvfs;
1961 }
1962
@@ -1970,8 +1976,7 @@ void *ebpf_vfs_thread(void *ptr)
1976 vfs_collector(em);
1977
1978 endvfs:
1973 - if (!em->enabled)
1974 - ebpf_update_disabled_plugin_stats(em);
1979 + ebpf_update_disabled_plugin_stats(em);
1980
1981 netdata_thread_cleanup_pop(1);
1982 return NULL;
libnetdata/ebpf/ebpf.h
+1
@@ -270,6 +270,7 @@ typedef struct ebpf_module {
270 netdata_ebpf_targets_t *targets;
271 struct bpf_link **probe_links;
272 struct bpf_object *objects;
273 + struct netdata_static_thread *thread;
274 } ebpf_module_t;
275
276 int ebpf_get_kernel_version();