diff options
Diffstat (limited to 'src/collectors/cgroups.plugin')
-rw-r--r-- | src/collectors/cgroups.plugin/cgroup-discovery.c | 20 | ||||
-rw-r--r-- | src/collectors/cgroups.plugin/cgroup-network.c | 30 | ||||
-rw-r--r-- | src/collectors/cgroups.plugin/sys_fs_cgroup.c | 72 |
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); |