summaryrefslogtreecommitdiffstats
path: root/src/collectors/cgroups.plugin
diff options
context:
space:
mode:
Diffstat (limited to 'src/collectors/cgroups.plugin')
-rw-r--r--src/collectors/cgroups.plugin/cgroup-discovery.c20
-rw-r--r--src/collectors/cgroups.plugin/cgroup-network.c30
-rw-r--r--src/collectors/cgroups.plugin/sys_fs_cgroup.c72
3 files changed, 60 insertions, 62 deletions
diff --git a/src/collectors/cgroups.plugin/cgroup-discovery.c b/src/collectors/cgroups.plugin/cgroup-discovery.c
index 61d5c08f..d880f8a7 100644
--- a/src/collectors/cgroups.plugin/cgroup-discovery.c
+++ b/src/collectors/cgroups.plugin/cgroup-discovery.c
@@ -178,11 +178,9 @@ static inline void discovery_rename_cgroup(struct cgroup *cg) {
netdata_log_debug(D_CGROUP, "looking for the name of cgroup '%s' with chart id '%s'", cg->id, cg->chart_id);
netdata_log_debug(D_CGROUP, "executing command %s \"%s\" for cgroup '%s'", cgroups_rename_script, cg->intermediate_id, cg->chart_id);
- pid_t cgroup_pid;
- FILE *fp_child_input, *fp_child_output;
- (void)netdata_popen_raw_default_flags_and_environment(&cgroup_pid, &fp_child_input, &fp_child_output, cgroups_rename_script, cg->id, cg->intermediate_id);
- if (!fp_child_output) {
+ POPEN_INSTANCE *instance = spawn_popen_run_variadic(cgroups_rename_script, cg->id, cg->intermediate_id, NULL);
+ if (!instance) {
collector_error("CGROUP: cannot popen(%s \"%s\", \"r\").", cgroups_rename_script, cg->intermediate_id);
cg->pending_renames = 0;
cg->processed = 1;
@@ -190,8 +188,8 @@ static inline void discovery_rename_cgroup(struct cgroup *cg) {
}
char buffer[CGROUP_CHARTID_LINE_MAX + 1];
- char *new_name = fgets(buffer, CGROUP_CHARTID_LINE_MAX, fp_child_output);
- int exit_code = netdata_pclose(fp_child_input, fp_child_output, cgroup_pid);
+ char *new_name = fgets(buffer, CGROUP_CHARTID_LINE_MAX, instance->child_stdout_fp);
+ int exit_code = spawn_popen_wait(instance);
switch (exit_code) {
case 0:
@@ -1085,7 +1083,6 @@ static void cgroup_cleanup_ebpf_integration()
static inline void read_cgroup_network_interfaces(struct cgroup *cg) {
netdata_log_debug(D_CGROUP, "looking for the network interfaces of cgroup '%s' with chart id '%s'", cg->id, cg->chart_id);
- pid_t cgroup_pid;
char cgroup_identifier[CGROUP_NETWORK_INTERFACE_MAX_LINE + 1];
if(!(cg->options & CGROUP_OPTIONS_IS_UNIFIED)) {
@@ -1096,16 +1093,15 @@ static inline void read_cgroup_network_interfaces(struct cgroup *cg) {
}
netdata_log_debug(D_CGROUP, "executing cgroup_identifier %s --cgroup '%s' for cgroup '%s'", cgroups_network_interface_script, cgroup_identifier, cg->id);
- FILE *fp_child_input, *fp_child_output;
- (void)netdata_popen_raw_default_flags_and_environment(&cgroup_pid, &fp_child_input, &fp_child_output, cgroups_network_interface_script, "--cgroup", cgroup_identifier);
- if(!fp_child_output) {
+ POPEN_INSTANCE *instance = spawn_popen_run_variadic(cgroups_network_interface_script, "--cgroup", cgroup_identifier, NULL);
+ if(!instance) {
collector_error("CGROUP: cannot popen(%s --cgroup \"%s\", \"r\").", cgroups_network_interface_script, cgroup_identifier);
return;
}
char *s;
char buffer[CGROUP_NETWORK_INTERFACE_MAX_LINE + 1];
- while((s = fgets(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, fp_child_output))) {
+ while((s = fgets(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, instance->child_stdout_fp))) {
trim(s);
if(*s && *s != '\n') {
@@ -1145,7 +1141,7 @@ static inline void read_cgroup_network_interfaces(struct cgroup *cg) {
}
}
- netdata_pclose(fp_child_input, fp_child_output, cgroup_pid);
+ spawn_popen_wait(instance);
}
static inline void discovery_process_cgroup(struct cgroup *cg) {
diff --git a/src/collectors/cgroups.plugin/cgroup-network.c b/src/collectors/cgroups.plugin/cgroup-network.c
index 685282e8..4cb5cbab 100644
--- a/src/collectors/cgroups.plugin/cgroup-network.c
+++ b/src/collectors/cgroups.plugin/cgroup-network.c
@@ -421,19 +421,19 @@ void detect_veth_interfaces(pid_t pid) {
host = read_proc_net_dev("host", netdata_configured_host_prefix);
if(!host) {
- errno = 0;
+ errno_clear();
collector_error("cannot read host interface list.");
goto cleanup;
}
if(!eligible_ifaces(host)) {
- errno = 0;
+ errno_clear();
collector_info("there are no double-linked host interfaces available.");
goto cleanup;
}
if(switch_namespace(netdata_configured_host_prefix, pid)) {
- errno = 0;
+ errno_clear();
collector_error("cannot switch to the namespace of pid %u", (unsigned int) pid);
goto cleanup;
}
@@ -444,13 +444,13 @@ void detect_veth_interfaces(pid_t pid) {
cgroup = read_proc_net_dev("cgroup", NULL);
if(!cgroup) {
- errno = 0;
+ errno_clear();
collector_error("cannot read cgroup interface list.");
goto cleanup;
}
if(!eligible_ifaces(cgroup)) {
- errno = 0;
+ errno_clear();
collector_error("there are not double-linked cgroup interfaces available.");
goto cleanup;
}
@@ -505,22 +505,20 @@ void call_the_helper(pid_t pid, const char *cgroup) {
collector_info("running: %s", command);
- pid_t cgroup_pid;
- FILE *fp_child_input, *fp_child_output;
+ POPEN_INSTANCE *pi;
- if(cgroup) {
- (void)netdata_popen_raw_default_flags(&cgroup_pid, environment, &fp_child_input, &fp_child_output, PLUGINS_DIR "/cgroup-network-helper.sh", "--cgroup", cgroup);
- }
+ if(cgroup)
+ pi = spawn_popen_run_variadic(PLUGINS_DIR "/cgroup-network-helper.sh", "--cgroup", cgroup, NULL);
else {
char buffer[100];
snprintfz(buffer, sizeof(buffer) - 1, "%d", pid);
- (void)netdata_popen_raw_default_flags(&cgroup_pid, environment, &fp_child_input, &fp_child_output, PLUGINS_DIR "/cgroup-network-helper.sh", "--pid", buffer);
+ pi = spawn_popen_run_variadic(PLUGINS_DIR "/cgroup-network-helper.sh", "--pid", buffer, NULL);
}
- if(fp_child_output) {
+ if(pi) {
char buffer[CGROUP_NETWORK_INTERFACE_MAX_LINE + 1];
char *s;
- while((s = fgets(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, fp_child_output))) {
+ while((s = fgets(buffer, CGROUP_NETWORK_INTERFACE_MAX_LINE, pi->child_stdout_fp))) {
trim(s);
if(*s && *s != '\n') {
@@ -536,7 +534,7 @@ void call_the_helper(pid_t pid, const char *cgroup) {
}
}
- netdata_pclose(fp_child_input, fp_child_output, cgroup_pid);
+ spawn_popen_kill(pi);
}
else
collector_error("cannot execute cgroup-network helper script: %s", command);
@@ -701,7 +699,7 @@ int main(int argc, char **argv) {
pid = atoi(argv[arg+1]);
if(pid <= 0) {
- errno = 0;
+ errno_clear();
collector_error("Invalid pid %d given", (int) pid);
return 2;
}
@@ -719,7 +717,7 @@ int main(int argc, char **argv) {
if(helper) call_the_helper(pid, cgroup);
if(pid <= 0 && !detected_devices) {
- errno = 0;
+ errno_clear();
collector_error("Cannot find a cgroup PID from cgroup '%s'", cgroup);
}
}
diff --git a/src/collectors/cgroups.plugin/sys_fs_cgroup.c b/src/collectors/cgroups.plugin/sys_fs_cgroup.c
index 59215240..5fdefa86 100644
--- a/src/collectors/cgroups.plugin/sys_fs_cgroup.c
+++ b/src/collectors/cgroups.plugin/sys_fs_cgroup.c
@@ -73,30 +73,19 @@ struct discovery_thread discovery_thread;
#define MAXSIZE_PROC_CMDLINE 4096
static enum cgroups_systemd_setting cgroups_detect_systemd(const char *exec)
{
- pid_t command_pid;
enum cgroups_systemd_setting retval = SYSTEMD_CGROUP_ERR;
char buf[MAXSIZE_PROC_CMDLINE];
char *begin, *end;
- FILE *fp_child_input;
- FILE *fp_child_output = netdata_popen(exec, &command_pid, &fp_child_input);
-
- if (!fp_child_output)
- return retval;
-
- int fd = fileno(fp_child_output);
- if (fd == -1 ) {
- collector_error("Cannot get the output of \"%s\": failed to get file descriptor", exec);
- netdata_pclose(fp_child_input, fp_child_output, command_pid);
+ POPEN_INSTANCE *pi = spawn_popen_run(exec);
+ if(!pi)
return retval;
- }
struct pollfd pfd;
- pfd.fd = fd;
+ pfd.fd = spawn_server_instance_read_fd(pi->si);
pfd.events = POLLIN;
int timeout = 3000; // milliseconds
-
int ret = poll(&pfd, 1, timeout);
if (ret == -1) {
@@ -104,7 +93,7 @@ static enum cgroups_systemd_setting cgroups_detect_systemd(const char *exec)
} else if (ret == 0) {
collector_info("Cannot get the output of \"%s\" within timeout (%d ms)", exec, timeout);
} else {
- while (fgets(buf, MAXSIZE_PROC_CMDLINE, fp_child_output) != NULL) {
+ while (fgets(buf, MAXSIZE_PROC_CMDLINE, pi->child_stdout_fp) != NULL) {
if ((begin = strstr(buf, SYSTEMD_HIERARCHY_STRING))) {
end = begin = begin + strlen(SYSTEMD_HIERARCHY_STRING);
if (!*begin)
@@ -123,7 +112,7 @@ static enum cgroups_systemd_setting cgroups_detect_systemd(const char *exec)
}
}
- if (netdata_pclose(fp_child_input, fp_child_output, command_pid))
+ if(spawn_popen_wait(pi) != 0)
return SYSTEMD_CGROUP_ERR;
return retval;
@@ -131,41 +120,56 @@ static enum cgroups_systemd_setting cgroups_detect_systemd(const char *exec)
static enum cgroups_type cgroups_try_detect_version()
{
- pid_t command_pid;
+ char filename[FILENAME_MAX + 1];
+ snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/fs/cgroup");
+ struct statfs fsinfo;
+
+ // https://github.com/systemd/systemd/blob/main/docs/CGROUP_DELEGATION.md#three-different-tree-setups-
+ // ├── statfs("/sys/fs/cgroup/")
+ // │ └── .f_type
+ // │ ├── CGROUP2_SUPER_MAGIC (Unified mode)
+ // │ └── TMPFS_MAGIC (Legacy or Hybrid mode)
+ // ├── statfs("/sys/fs/cgroup/unified/")
+ // │ └── .f_type
+ // │ ├── CGROUP2_SUPER_MAGIC (Hybrid mode)
+ // │ └── Otherwise, you're in legacy mode
+ if (!statfs(filename, &fsinfo)) {
+#if defined CGROUP2_SUPER_MAGIC
+ if (fsinfo.f_type == CGROUP2_SUPER_MAGIC)
+ return CGROUPS_V2;
+#endif
+#if defined TMPFS_MAGIC
+ if (fsinfo.f_type == TMPFS_MAGIC) {
+ // either hybrid or legacy
+ return CGROUPS_V1;
+ }
+#endif
+ }
+
+ collector_info("cgroups version: can't detect using statfs (fs type), falling back to heuristics.");
+
char buf[MAXSIZE_PROC_CMDLINE];
enum cgroups_systemd_setting systemd_setting;
int cgroups2_available = 0;
// 1. check if cgroups2 available on system at all
- FILE *fp_child_input;
- FILE *fp_child_output = netdata_popen("grep cgroup /proc/filesystems", &command_pid, &fp_child_input);
- if (!fp_child_output) {
- collector_error("popen failed");
+ POPEN_INSTANCE *instance = spawn_popen_run("grep cgroup /proc/filesystems");
+ if(!instance) {
+ collector_error("cannot run 'grep cgroup /proc/filesystems'");
return CGROUPS_AUTODETECT_FAIL;
}
- while (fgets(buf, MAXSIZE_PROC_CMDLINE, fp_child_output) != NULL) {
+ while (fgets(buf, MAXSIZE_PROC_CMDLINE, instance->child_stdout_fp) != NULL) {
if (strstr(buf, "cgroup2")) {
cgroups2_available = 1;
break;
}
}
- if(netdata_pclose(fp_child_input, fp_child_output, command_pid))
+ if(spawn_popen_wait(instance) != 0)
return CGROUPS_AUTODETECT_FAIL;
if(!cgroups2_available)
return CGROUPS_V1;
-#if defined CGROUP2_SUPER_MAGIC
- // 2. check filesystem type for the default mountpoint
- char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/fs/cgroup");
- struct statfs fsinfo;
- if (!statfs(filename, &fsinfo)) {
- if (fsinfo.f_type == CGROUP2_SUPER_MAGIC)
- return CGROUPS_V2;
- }
-#endif
-
// 3. check systemd compiletime setting
if ((systemd_setting = cgroups_detect_systemd("systemd --version")) == SYSTEMD_CGROUP_ERR)
systemd_setting = cgroups_detect_systemd(SYSTEMD_CMD_RHEL);