cgroup-network search for PIDs in sub-cgroups; also it works even when there are no veth interfaces at the system; fixes #3199
Costa Tsaousis (ktsaou) committed
Jan 4, 2018 at 18:41 UTC
4d061299d1eb0103c484d973e5b058b53031cabd
1 file changed
+69
-22
src/cgroup-network.c
+69
-22
@@ -247,25 +247,18 @@ int switch_namespace(const char *prefix, pid_t pid) {
247
#endif
248
}
249
250
-pid_t read_pid_from_cgroup(const char *path) {
251
- char buffer[FILENAME_MAX + 1];
252
-
253
- snprintfz(buffer, FILENAME_MAX, "%s/cgroup.procs", path);
254
- FILE *fp = fopen(buffer, "r");
250
+pid_t read_pid_from_cgroup_file(const char *filename) {
251
+ FILE *fp = fopen(filename, "r");
252
if(!fp) {
256
- error("Cannot read file '%s'.", buffer);
257
- snprintfz(buffer, FILENAME_MAX, "%s/tasks", path);
258
- fp = fopen(buffer, "r");
259
- }
260
-
261
- if(!fp) {
262
- error("Cannot read file '%s'.", buffer);
253
+ error("Cannot read file '%s'.", filename);
254
return 0;
255
}
256
257
+ char buffer[100 + 1];
258
pid_t pid = 0;
259
char *s;
268
- while((s = fgets(buffer, FILENAME_MAX, fp))) {
260
+ while((s = fgets(buffer, 100, fp))) {
261
+ buffer[100] = '\0';
262
pid = atoi(s);
263
if(pid > 0) break;
264
}
@@ -274,6 +267,46 @@ pid_t read_pid_from_cgroup(const char *path) {
267
return pid;
268
}
269
270
+pid_t read_pid_from_cgroup_files(const char *path) {
271
+ char filename[FILENAME_MAX + 1];
272
+
273
+ snprintfz(filename, FILENAME_MAX, "%s/cgroup.procs", path);
274
+ pid_t pid = read_pid_from_cgroup_file(filename);
275
+ if(pid > 0) return pid;
276
+
277
+ snprintfz(filename, FILENAME_MAX, "%s/tasks", path);
278
+ return read_pid_from_cgroup_file(filename);
279
+}
280
+
281
+pid_t read_pid_from_cgroup(const char *path) {
282
+ pid_t pid = read_pid_from_cgroup_files(path);
283
+ if (pid > 0) return pid;
284
+
285
+ DIR *dir = opendir(path);
286
+ if (!dir) {
287
+ error("cannot read directory '%s'", path);
288
+ return 0;
289
+ }
290
+
291
+ struct dirent *de = NULL;
292
+ while ((de = readdir(dir))) {
293
+ if (de->d_type == DT_DIR
294
+ && (
295
+ (de->d_name[0] == '.' && de->d_name[1] == '\0')
296
+ || (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')
297
+ ))
298
+ continue;
299
+
300
+ if (de->d_type == DT_DIR) {
301
+ char filename[FILENAME_MAX + 1];
302
+ snprintfz(filename, FILENAME_MAX, "%s/%s", path, de->d_name);
303
+ pid = read_pid_from_cgroup(filename);
304
+ if(pid > 0) break;
305
+ }
306
+ }
307
+ closedir(dir);
308
+ return pid;
309
+}
310
311
// ----------------------------------------------------------------------------
312
// send the result to netdata
@@ -337,18 +370,30 @@ void detect_veth_interfaces(pid_t pid) {
370
if(!host)
371
fatal("cannot read host interface list.");
372
340
- if(!eligible_ifaces(host))
341
- fatal("there are no double-linked host interfaces available.");
373
+ if(!eligible_ifaces(host)) {
374
+ errno = 0;
375
+ error("there are no double-linked host interfaces available.");
376
+ return;
377
+ }
378
343
- if(switch_namespace(prefix, pid))
344
- fatal("cannot switch to the namespace of pid %u", (unsigned int)pid);
379
+ if(switch_namespace(prefix, pid)) {
380
+ errno = 0;
381
+ error("cannot switch to the namespace of pid %u", (unsigned int) pid);
382
+ return;
383
+ }
384
385
cgroup = read_proc_net_dev(NULL);
347
- if(!cgroup)
348
- fatal("cannot read cgroup interface list.");
386
+ if(!cgroup) {
387
+ errno = 0;
388
+ error("cannot read cgroup interface list.");
389
+ return;
390
+ }
391
350
- if(!eligible_ifaces(cgroup))
351
- fatal("there are not double-linked cgroup interfaces available.");
392
+ if(!eligible_ifaces(cgroup)) {
393
+ errno = 0;
394
+ error("there are not double-linked cgroup interfaces available.");
395
+ return;
396
+ }
397
398
for(h = host; h ; h = h->next) {
399
if(iface_is_eligible(h)) {
@@ -462,5 +507,7 @@ int main(int argc, char **argv) {
507
if(pid > 0)
508
detect_veth_interfaces(pid);
509
465
- return send_devices();
510
+ int found = send_devices();
511
+ if(found <= 0) return 1;
512
+ return 0;
513
}