Improve thread shutdown handling for MSSQL plugin (#20725)
Stelios Fragkakis committed
Jul 28, 2025 at 20:49 UTC
21e6f6fc0d13b7028c5693afffe98a90de1f89ed
3 files changed
+97
-34
src/collectors/windows.plugin/perflib-mssql.c
+9
-1
@@ -1142,6 +1142,8 @@ void *netdata_mssql_queries(void *ptr __maybe_unused)
1142
return NULL;
1143
}
1144
1145
+static ND_THREAD *mssql_queries_thread = NULL;
1146
+
1147
static int initialize(int update_every)
1148
{
1149
static bool create_thread = false;
@@ -1155,7 +1157,7 @@ static int initialize(int update_every)
1157
}
1158
1159
if (create_thread)
1158
- nd_thread_create("mssql_queries", NETDATA_THREAD_OPTION_DEFAULT, netdata_mssql_queries, &update_every);
1160
+ mssql_queries_thread = nd_thread_create("mssql_queries", NETDATA_THREAD_OPTION_DEFAULT, netdata_mssql_queries, &update_every);
1161
1162
return 0;
1163
}
@@ -2565,3 +2567,9 @@ int do_PerflibMSSQL(int update_every, usec_t dt __maybe_unused)
2567
2568
return 0;
2569
}
2570
+
2571
+void do_PerflibMSSQL_cleanup()
2572
+{
2573
+ if (nd_thread_join(mssql_queries_thread))
2574
+ nd_log_daemon(NDLP_ERR, "Failed to join mssql queries thread");
2575
+}
src/collectors/windows.plugin/windows_plugin.c
+87
-33
@@ -12,6 +12,7 @@ static struct proc_module {
12
int (*func)(int update_every, usec_t dt);
13
RRDDIM *rd;
14
ND_THREAD *thread;
15
+ void (*cleanup)();
16
} win_modules[] = {
17
18
// system metrics
@@ -19,17 +20,26 @@ static struct proc_module {
20
.dim = "GetSystemUptime",
21
.enabled = CONFIG_BOOLEAN_YES,
22
.update_every = UPDATE_EVERY_MIN,
22
- .func = do_GetSystemUptime},
23
+ .func = do_GetSystemUptime,
24
+ .rd = NULL,
25
+ .thread = NULL,
26
+ .cleanup = NULL},
27
{.name = "GetSystemRAM",
28
.dim = "GetSystemRAM",
29
.enabled = CONFIG_BOOLEAN_YES,
30
.update_every = UPDATE_EVERY_MIN,
27
- .func = do_GetSystemRAM},
31
+ .func = do_GetSystemRAM,
32
+ .rd = NULL,
33
+ .thread = NULL,
34
+ .cleanup = NULL},
35
{.name = "GetPowerSupply",
36
.dim = "GetPowerSupply",
37
.enabled = CONFIG_BOOLEAN_YES,
38
.update_every = UPDATE_EVERY_MIN,
32
- .func = do_GetPowerSupply},
39
+ .func = do_GetPowerSupply,
40
+ .rd = NULL,
41
+ .thread = NULL,
42
+ .cleanup = NULL},
43
{.name = "PerflibServices",
44
.dim = "PerflibServices",
45
.enabled = CONFIG_BOOLEAN_YES,
@@ -44,99 +54,141 @@ static struct proc_module {
54
.dim = "PerflibProcesses",
55
.enabled = CONFIG_BOOLEAN_YES,
56
.update_every = UPDATE_EVERY_MIN,
47
- .func = do_PerflibProcesses},
57
+ .func = do_PerflibProcesses,
58
+ .rd = NULL,
59
+ .thread = NULL,
60
+ .cleanup = NULL},
61
{.name = "PerflibProcessor",
62
.dim = "PerflibProcessor",
63
.enabled = CONFIG_BOOLEAN_YES,
64
.update_every = UPDATE_EVERY_MIN,
52
- .func = do_PerflibProcessor},
65
+ .func = do_PerflibProcessor,
66
+ .rd = NULL,
67
+ .thread = NULL,
68
+ .cleanup = NULL},
69
{.name = "PerflibMemory",
70
.dim = "PerflibMemory",
71
.enabled = CONFIG_BOOLEAN_YES,
72
.update_every = UPDATE_EVERY_MIN,
57
- .func = do_PerflibMemory},
73
+ .func = do_PerflibMemory,
74
+ .rd = NULL,
75
+ .thread = NULL,
76
+ .cleanup = NULL},
77
{.name = "PerflibStorage",
78
.dim = "PerflibStorage",
79
.enabled = CONFIG_BOOLEAN_YES,
80
.update_every = UPDATE_EVERY_MIN,
62
- .func = do_PerflibStorage},
81
+ .func = do_PerflibStorage,
82
+ .rd = NULL,
83
+ .thread = NULL,
84
+ .cleanup = NULL},
85
{.name = "PerflibNetwork",
86
.dim = "PerflibNetwork",
87
.enabled = CONFIG_BOOLEAN_YES,
88
.update_every = UPDATE_EVERY_MIN,
67
- .func = do_PerflibNetwork},
89
+ .func = do_PerflibNetwork,
90
+ .rd = NULL,
91
+ .thread = NULL,
92
+ .cleanup = NULL},
93
{.name = "PerflibObjects",
94
.dim = "PerflibObjects",
95
.enabled = CONFIG_BOOLEAN_YES,
96
.update_every = UPDATE_EVERY_MIN,
72
- .func = do_PerflibObjects},
97
+ .func = do_PerflibObjects,
98
+ .rd = NULL,
99
+ .thread = NULL,
100
+ .cleanup = NULL},
101
{.name = "PerflibHyperV",
102
.dim = "PerflibHyperV",
103
.enabled = CONFIG_BOOLEAN_YES,
104
.update_every = 5 * UPDATE_EVERY_MIN,
77
- .func = do_PerflibHyperV},
78
-
105
+ .func = do_PerflibHyperV,
106
+ .rd = NULL,
107
+ .thread = NULL,
108
+ .cleanup = NULL},
109
{.name = "PerflibThermalZone",
110
.dim = "PerflibThermalZone",
111
.enabled = CONFIG_BOOLEAN_NO,
112
.update_every = 5 * UPDATE_EVERY_MIN,
83
- .func = do_PerflibThermalZone},
84
-
113
+ .func = do_PerflibThermalZone,
114
+ .rd = NULL,
115
+ .thread = NULL,
116
+ .cleanup = NULL},
117
{.name = "PerflibWebService",
118
.dim = "PerflibWebService",
119
.enabled = CONFIG_BOOLEAN_YES,
120
.update_every = UPDATE_EVERY_MIN,
89
- .func = do_PerflibWebService},
121
+ .func = do_PerflibWebService,
122
+ .rd = NULL,
123
+ .thread = NULL,
124
+ .cleanup = NULL},
125
{.name = "PerflibMSSQL",
126
.dim = "PerflibMSSQL",
127
.enabled = CONFIG_BOOLEAN_YES,
128
.update_every = 10 * UPDATE_EVERY_MIN,
94
- .func = do_PerflibMSSQL},
95
-
129
+ .func = do_PerflibMSSQL,
130
+ .rd = NULL,
131
+ .thread = NULL,
132
+ .cleanup = do_PerflibMSSQL_cleanup},
133
{.name = "PerflibNetFramework",
134
.dim = "PerflibNetFramework",
135
.enabled = CONFIG_BOOLEAN_YES,
136
.update_every = UPDATE_EVERY_MIN,
100
- .func = do_PerflibNetFramework},
137
+ .func = do_PerflibNetFramework,
138
+ .rd = NULL,
139
+ .thread = NULL,
140
+ .cleanup = NULL},
141
{.name = "PerflibAD",
142
.dim = "PerflibAD",
143
.enabled = CONFIG_BOOLEAN_YES,
144
.update_every = 10 * UPDATE_EVERY_MIN,
105
- .func = do_PerflibAD},
106
-
145
+ .func = do_PerflibAD,
146
+ .rd = NULL,
147
+ .thread = NULL,
148
+ .cleanup = NULL},
149
{.name = "PerflibADCS",
150
.dim = "PerflibADCS",
151
.enabled = CONFIG_BOOLEAN_YES,
152
.update_every = 10 * UPDATE_EVERY_MIN,
111
- .func = do_PerflibADCS},
112
-
153
+ .func = do_PerflibADCS,
154
+ .rd = NULL,
155
+ .thread = NULL,
156
+ .cleanup = NULL},
157
{.name = "PerflibADFS",
158
.dim = "PerflibADFS",
159
.enabled = CONFIG_BOOLEAN_YES,
160
.update_every = 10 * UPDATE_EVERY_MIN,
117
- .func = do_PerflibADFS},
118
-
161
+ .func = do_PerflibADFS,
162
+ .rd = NULL,
163
+ .thread = NULL,
164
+ .cleanup = NULL},
165
{.name = "PerflibExchange",
166
.dim = "PerflibExchange",
167
.enabled = CONFIG_BOOLEAN_YES,
168
.update_every = 10 * UPDATE_EVERY_MIN,
123
- .func = do_PerflibExchange},
124
-
169
+ .func = do_PerflibExchange,
170
+ .rd = NULL,
171
+ .thread = NULL,
172
+ .cleanup = NULL},
173
{.name = "PerflibNUMA",
174
.dim = "PerflibNUMA",
175
.enabled = CONFIG_BOOLEAN_YES,
176
.update_every = UPDATE_EVERY_MIN,
129
- .func = do_PerflibNUMA},
130
-
177
+ .func = do_PerflibNUMA,
178
+ .rd = NULL,
179
+ .thread = NULL,
180
+ .cleanup = NULL},
181
// the terminator of this array
182
{.name = "PerflibASP",
183
.dim = "PerflibASP",
184
.enabled = CONFIG_BOOLEAN_YES,
185
.update_every = UPDATE_EVERY_MIN,
136
- .func = do_PerflibASP},
137
-
186
+ .func = do_PerflibASP,
187
+ .rd = NULL,
188
+ .thread = NULL,
189
+ .cleanup = NULL},
190
// the terminator of this array
139
- {.name = NULL, .dim = NULL, .func = NULL}};
191
+ {.name = NULL, .dim = NULL, .func = NULL, .rd = NULL, .thread = NULL, .cleanup = NULL}};
192
193
#if WORKER_UTILIZATION_MAX_JOB_TYPES < 36
194
#error WORKER_UTILIZATION_MAX_JOB_TYPES has to be at least 36
@@ -206,8 +258,6 @@ void *win_plugin_main(void *ptr)
258
int update_every = localhost->rrd_update_every;
259
for (i = 0; win_modules[i].name; i++) {
260
struct proc_module *pm = &win_modules[i];
209
- pm->thread = NULL;
210
-
261
snprintfz(buf, CONFIG_MAX_NAME, "plugin:windows:%s", pm->name);
262
263
pm->enabled = inicfg_get_boolean(&netdata_config, "plugin:windows", pm->name, pm->enabled);
@@ -267,8 +317,12 @@ void *win_plugin_main(void *ptr)
317
// Join threads
318
for (i = 0; win_modules[i].name; i++) {
319
struct proc_module *pm = &win_modules[i];
270
- if (pm->thread)
320
+ if (pm->cleanup)
321
+ pm->cleanup();
322
+
323
+ if (pm->thread) {
324
nd_thread_join(pm->thread);
325
+ }
326
}
327
return NULL;
328
}
src/collectors/windows.plugin/windows_plugin.h
+1
@@ -36,6 +36,7 @@ int do_PerflibObjects(int update_every, usec_t dt);
36
int do_PerflibThermalZone(int update_every, usec_t dt);
37
int do_PerflibWebService(int update_every, usec_t dt);
38
int do_PerflibMSSQL(int update_every, usec_t dt);
39
+void do_PerflibMSSQL_cleanup();
40
int do_PerflibNetFramework(int update_every, usec_t dt);
41
int do_PerflibAD(int update_every, usec_t dt);
42
int do_PerflibADCS(int update_every, usec_t dt);