[gnome-system-monitor] Cgroup reform



commit 2c1c564401ad42f24a73a162210bba0e0623fb1f
Author: Artem Vorotnikov <artem vorotnikov me>
Date:   Sun Oct 16 10:39:14 2016 +0300

    Cgroup reform
    
    https://bugzilla.gnome.org/show_bug.cgi?id=773016

 src/cgroups.cpp   |  201 +++++++++-------------------------------------------
 src/cgroups.h     |    6 +-
 src/proctable.cpp |    4 +-
 3 files changed, 39 insertions(+), 172 deletions(-)
---
diff --git a/src/cgroups.cpp b/src/cgroups.cpp
index 603e95f..b75b9fb 100644
--- a/src/cgroups.cpp
+++ b/src/cgroups.cpp
@@ -1,189 +1,58 @@
 /* -*- 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 "application.h"
 #include "util.h"
 
-gboolean
+bool
 cgroups_enabled(void)
 {
-    static gboolean initialized = FALSE;
-    static gboolean has_cgroups;
+    static bool initialized = false;
+    static bool has_cgroups;
 
-    if (!initialized) {
-        initialized = TRUE;
-        has_cgroups = g_file_test("/proc/cgroups", G_FILE_TEST_EXISTS);
+    if (not initialized) {
+        initialized = true;
+        has_cgroups = Glib::file_test("/proc/cgroups", Glib::FileTest::FILE_TEST_EXISTS);
     }
 
     return has_cgroups;
 }
 
-static void
-append_cgroup_name(char *line, gchar **current_cgroup_name)
-{
-    gchar *controller, *path, *tmp, *path_plus_space;
-    int paren_offset, off, tmp_size;
-
-    controller = g_strstr_len(line, -1, ":") + 1;
-    if (!controller)
-        return;
+static std::pair<Glib::ustring, Glib::ustring>
+parse_cgroup_line(const Glib::ustring& line) {
+    auto split = std::vector<Glib::ustring>(Glib::Regex::split_simple(":", line));
+    if (split.size() < 3) { return std::make_pair("", ""); }
+    auto cgroups = split.at(2);
+    if (cgroups.empty() || cgroups == "/") { return std::make_pair("", ""); }
+    auto category = split.at(1);
+    if (category.find("name=") != category.npos) { return std::make_pair("", ""); }
 
-    path = g_strstr_len(controller, -1, ":") + 1;
-    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;
+    return std::make_pair(category, cgroups);
 }
 
-static int
-check_cgroup_changed(gchar *line, gchar *current_cgroup_set)
-{
-    /* check if line is contained in current_cgroup_set */
-    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';
+static Glib::ustring
+get_process_cgroup_string(unsigned int pid) {
+    if (not cgroups_enabled())
+        return "";
 
-    if (std::strncmp(controller, "name=", 5) == 0)
-        goto out;
-
-    /* if there are multiple controllers just report string has changed */
-    if (g_strstr_len(controller, -1, ",")) {
-        ret = 1;
-        goto out;
-    }
-
-    if (!current_cgroup_set) {
-        if (std::strcmp(path, "/") != 0)
-            ret = 1;
-        goto out;
-    }
+    /* read out of /proc/pid/cgroup */
+    auto path = Glib::ustring::compose("/proc/%1/cgroup", pid);
+    Glib::ustring text;
+    try { text = Glib::file_get_contents(path); } catch (...) { return ""; }
+    auto lines = std::vector<Glib::ustring>(Glib::Regex::split_simple("\n", text));
 
-    /* special case for root cgroup */
-    tmp = current_cgroup_set;
-    if (std::strcmp(path, "/") == 0) {
-        while ((found = g_strstr_len(tmp, -1, controller))) {
-            close_paren = g_strstr_len(found, -1, ")");
-            open_paren = g_strstr_len(found, -1, "(");
-            if (close_paren) {
-                if (!open_paren || (close_paren < open_paren)) {
-                    ret = 1;
-                    goto out;
-                }
-            }
-            tmp = found + strlen(controller);
-        }
-        goto out;
+    Glib::ustring cgroup_string;
+    for (auto& line : lines) {
+        auto data = parse_cgroup_line(line);
+        if (data.first.empty() || data.second.empty()) { continue; }
+        if (!cgroup_string.empty()) { cgroup_string += ", "; }
+        cgroup_string += Glib::ustring::compose("%1 (%2)", data.second, data.first);
     }
 
-    tmp = current_cgroup_set;
-    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;
+    return cgroup_string;
 }
 
-void
-get_process_cgroup_info(ProcInfo *info)
-{
-    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;
-    }
+void get_process_cgroup_info(ProcInfo& info) {
+    auto cgroup_string = get_process_cgroup_string(info.pid);
 
-    g_strfreev(lines);
-out:
-    g_free(path);
+    g_free(info.cgroup_name);
+    info.cgroup_name = cgroup_string.empty() ? nullptr : g_strdup(cgroup_string.c_str());
 }
diff --git a/src/cgroups.h b/src/cgroups.h
index ec0f4d7..7ddafea 100644
--- a/src/cgroups.h
+++ b/src/cgroups.h
@@ -2,11 +2,9 @@
 #ifndef _GSM_CGROUPS_H_
 #define _GSM_CGROUPS_H_
 
-#include <glib.h>
-
 #include "application.h"
 
-void get_process_cgroup_info (ProcInfo *info);
-gboolean cgroups_enabled (void);
+void get_process_cgroup_info (ProcInfo& info);
+bool cgroups_enabled ();
 
 #endif /* _GSM_CGROUPS_H_ */
diff --git a/src/proctable.cpp b/src/proctable.cpp
index 208a289..82c4f82 100644
--- a/src/proctable.cpp
+++ b/src/proctable.cpp
@@ -914,7 +914,7 @@ update_info (GsmApplication *app, ProcInfo *info)
     g_assert(info->ppid != -1 || info->pid == 0);
 
     /* get cgroup data */
-    get_process_cgroup_info(info);
+    get_process_cgroup_info(*info);
 
     procman::get_process_systemd_info(info);
 }
@@ -964,7 +964,7 @@ ProcInfo::ProcInfo(pid_t pid)
 
     get_process_selinux_context (info);
     info->cgroup_name = NULL;
-    get_process_cgroup_info(info);
+    get_process_cgroup_info(*info);
 
     info->unit = info->session = info->seat = NULL;
     get_process_systemd_info(info);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]