Commit 2c1c5644 authored by Artem Vorotnikov's avatar Artem Vorotnikov Committed by Robert Roth
parent 07b570c6
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
#include <config.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <cstring>
#include "cgroups.h" #include "cgroups.h"
#include "application.h"
#include "util.h" #include "util.h"
gboolean bool
cgroups_enabled(void) cgroups_enabled(void)
{ {
static gboolean initialized = FALSE; static bool initialized = false;
static gboolean has_cgroups; static bool has_cgroups;
if (!initialized) { if (not initialized) {
initialized = TRUE; initialized = true;
has_cgroups = g_file_test("/proc/cgroups", G_FILE_TEST_EXISTS); has_cgroups = Glib::file_test("/proc/cgroups", Glib::FileTest::FILE_TEST_EXISTS);
} }
return has_cgroups; return has_cgroups;
} }
static void static std::pair<Glib::ustring, Glib::ustring>
append_cgroup_name(char *line, gchar **current_cgroup_name) parse_cgroup_line(const Glib::ustring& line) {
{ auto split = std::vector<Glib::ustring>(Glib::Regex::split_simple(":", line));
gchar *controller, *path, *tmp, *path_plus_space; if (split.size() < 3) { return std::make_pair("", ""); }
int paren_offset, off, tmp_size; auto cgroups = split.at(2);
if (cgroups.empty() || cgroups == "/") { return std::make_pair("", ""); }
controller = g_strstr_len(line, -1, ":") + 1; auto category = split.at(1);
if (!controller) if (category.find("name=") != category.npos) { return std::make_pair("", ""); }
return;
path = g_strstr_len(controller, -1, ":") + 1; return std::make_pair(category, cgroups);
if (!path)
return;
*(path - 1) = '\0';
g_strdelimit(controller, ",", '/');
if ((std::strcmp(path, "/") == 0) || (std::strncmp(controller, "name=", 5) == 0))
return;
if (*current_cgroup_name == NULL) {
*current_cgroup_name = g_strdup_printf("%s (%s)", path, controller);
return;
}
/* add a space to the end of the path string */
path_plus_space = g_strdup_printf("%s ", path);
if ((tmp = g_strstr_len(*current_cgroup_name, -1, path_plus_space))) {
tmp_size = strlen(*current_cgroup_name) + strlen(controller) + 1;
paren_offset = g_strstr_len(tmp + strlen(path), -1, ")") - *current_cgroup_name;
*(*current_cgroup_name + paren_offset) = '\0';
tmp = (gchar *)g_strnfill(tmp_size, '\0');
off = g_strlcat(tmp, *current_cgroup_name, tmp_size);
*(tmp + off) = '/';
off++;
off += g_strlcat(tmp + off, controller, tmp_size);
*(tmp + off) = ')';
off++;
g_strlcat(tmp + off, *current_cgroup_name + paren_offset + 1, tmp_size);
} else
tmp = g_strdup_printf("%s, %s(%s)", *current_cgroup_name, path_plus_space, controller);
g_free(path_plus_space);
g_free(*current_cgroup_name);
*current_cgroup_name = tmp;
} }
static int static Glib::ustring
check_cgroup_changed(gchar *line, gchar *current_cgroup_set) get_process_cgroup_string(unsigned int pid) {
{ if (not cgroups_enabled())
/* check if line is contained in current_cgroup_set */ return "";
gchar *controller, *path, *tmp, *found, *close_paren, *open_paren;
int ret = 0;
controller = g_strstr_len(line, -1, ":") + 1;
if (!controller)
return 1;
path = g_strstr_len(controller, -1, ":") + 1;
if (!path)
return 1;
*(path - 1) = '\0';
if (std::strncmp(controller, "name=", 5) == 0) /* read out of /proc/pid/cgroup */
goto out; auto path = Glib::ustring::compose("/proc/%1/cgroup", pid);
Glib::ustring text;
/* if there are multiple controllers just report string has changed */ try { text = Glib::file_get_contents(path); } catch (...) { return ""; }
if (g_strstr_len(controller, -1, ",")) { auto lines = std::vector<Glib::ustring>(Glib::Regex::split_simple("\n", text));
ret = 1;
goto out;
}
if (!current_cgroup_set) {
if (std::strcmp(path, "/") != 0)
ret = 1;
goto out;
}
/* special case for root cgroup */ Glib::ustring cgroup_string;
tmp = current_cgroup_set; for (auto& line : lines) {
if (std::strcmp(path, "/") == 0) { auto data = parse_cgroup_line(line);
while ((found = g_strstr_len(tmp, -1, controller))) { if (data.first.empty() || data.second.empty()) { continue; }
close_paren = g_strstr_len(found, -1, ")"); if (!cgroup_string.empty()) { cgroup_string += ", "; }
open_paren = g_strstr_len(found, -1, "("); cgroup_string += Glib::ustring::compose("%1 (%2)", data.second, data.first);
if (close_paren) {
if (!open_paren || (close_paren < open_paren)) {
ret = 1;
goto out;
}
}
tmp = found + strlen(controller);
}
goto out;
} }
tmp = current_cgroup_set; return cgroup_string;
while ((found = g_strstr_len(tmp, -1, path))) {
found = found + strlen(path);
close_paren = g_strstr_len(found, -1, ")");
if (*found == ' ') {
if (g_strstr_len(found + 1, close_paren - found, controller))
goto out;
}
tmp = close_paren + 1;
}
ret = 1;
out:
*(path - 1) = ':';
return ret;
} }
void void get_process_cgroup_info(ProcInfo& info) {
get_process_cgroup_info(ProcInfo *info) auto cgroup_string = get_process_cgroup_string(info.pid);
{
gchar *path;
gchar *cgroup_name = NULL;
int cgroups_changed = 0;
gchar *text;
char **lines;
int i;
if (!cgroups_enabled())
return;
/* read out of /proc/pid/cgroup */
path = g_strdup_printf("/proc/%d/cgroup", info->pid);
if (!path)
return;
if(!g_file_get_contents(path, &text, NULL, NULL))
goto out;
lines = g_strsplit(text, "\n", -1);
g_free(text);
if (!lines)
goto out;
for (i = 0; lines[i] != NULL; i++) {
if (lines[i][0] == '\0')
continue;
if (check_cgroup_changed(lines[i], info->cgroup_name)) {
cgroups_changed = 1;
break;
}
}
if (cgroups_changed) {
for (i = 0; lines[i] != NULL; i++) {
if (lines[i][0] == '\0')
continue;
append_cgroup_name(lines[i], &cgroup_name);
}
if (info->cgroup_name)
g_free(info->cgroup_name);
if (!cgroup_name)
info->cgroup_name = g_strdup("");
else
info->cgroup_name = cgroup_name;
}
g_strfreev(lines); g_free(info.cgroup_name);
out: info.cgroup_name = cgroup_string.empty() ? nullptr : g_strdup(cgroup_string.c_str());
g_free(path);
} }
...@@ -2,11 +2,9 @@ ...@@ -2,11 +2,9 @@
#ifndef _GSM_CGROUPS_H_ #ifndef _GSM_CGROUPS_H_
#define _GSM_CGROUPS_H_ #define _GSM_CGROUPS_H_
#include <glib.h>
#include "application.h" #include "application.h"
void get_process_cgroup_info (ProcInfo *info); void get_process_cgroup_info (ProcInfo& info);
gboolean cgroups_enabled (void); bool cgroups_enabled ();
#endif /* _GSM_CGROUPS_H_ */ #endif /* _GSM_CGROUPS_H_ */
...@@ -914,7 +914,7 @@ update_info (GsmApplication *app, ProcInfo *info) ...@@ -914,7 +914,7 @@ update_info (GsmApplication *app, ProcInfo *info)
g_assert(info->ppid != -1 || info->pid == 0); g_assert(info->ppid != -1 || info->pid == 0);
/* get cgroup data */ /* get cgroup data */
get_process_cgroup_info(info); get_process_cgroup_info(*info);
procman::get_process_systemd_info(info); procman::get_process_systemd_info(info);
} }
...@@ -964,7 +964,7 @@ ProcInfo::ProcInfo(pid_t pid) ...@@ -964,7 +964,7 @@ ProcInfo::ProcInfo(pid_t pid)
get_process_selinux_context (info); get_process_selinux_context (info);
info->cgroup_name = NULL; info->cgroup_name = NULL;
get_process_cgroup_info(info); get_process_cgroup_info(*info);
info->unit = info->session = info->seat = NULL; info->unit = info->session = info->seat = NULL;
get_process_systemd_info(info); get_process_systemd_info(info);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment