/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include #include "cgroups.h" #include "util.h" #include #include #include bool cgroups_enabled(void) { static bool initialized = false; static bool has_cgroups; if (not initialized) { initialized = true; has_cgroups = Glib::file_test("/proc/cgroups", Glib::FileTest::FILE_TEST_EXISTS); } return has_cgroups; } static const std::pair & parse_cgroup_line(const std::string& line) { static std::unordered_map> line_cache; auto it = line_cache.insert({line, {"", ""} }); if (it.second) { // inserted new std::string::size_type cat_start, name_start; if ((cat_start = line.find(':')) != std::string::npos && (name_start = line.find(':', cat_start + 1)) != std::string::npos) { // printf("%s %lu %lu\n", line.c_str(), cat_start, name_start); auto cat = line.substr(cat_start + 1, name_start - cat_start - 1); auto name = line.substr(name_start + 1); // strip the name= prefix if (cat.find("name=") == 0) { cat.erase(0, 5); } if (!name.empty() && name != "/") { it.first->second = {name, cat}; } } } return it.first->second; } static const std::string& get_process_cgroup_string(pid_t pid) { static std::unordered_map file_cache{ {"", ""} }; /* read out of /proc/pid/cgroup */ auto path = "/proc/" + std::to_string(pid) + "/cgroup"; std::string text; try { text = Glib::file_get_contents(path); } catch (...) { return file_cache[""]; } auto it = file_cache.insert({ text, "" }); if (it.second) { // inserted new // name -> [cat...], sorted by name; std::map> names; std::string::size_type last = 0, eol; // for each line in the file while ((eol = text.find('\n', last)) != std::string::npos) { auto line = text.substr(last, eol - last); last = eol + 1; const auto& p = parse_cgroup_line(line); if (!p.first.empty()) { names[p.first].push_back(p.second); } } // name (cat1, cat2), ... // sorted by name, categories std::vector groups; for (auto& i : names) { std::sort(begin(i.second), end(i.second)); std::string cats = procman::join(i.second, ", "); groups.push_back(i.first + " (" + cats + ')'); } it.first->second = procman::join(groups, ", "); } return it.first->second; } void get_process_cgroup_info(ProcInfo& info) { if (not cgroups_enabled()) return; const auto& cgroup_string = get_process_cgroup_string(info.pid); info.cgroup_name = cgroup_string; }