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();