This is an automated email from the ASF dual-hosted git repository.
bmahler pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mesos.git
The following commit(s) were added to refs/heads/master by this push:
new ea928cee4 [cgroups2] Made `cgroups2::processes` optionally recursive.
ea928cee4 is described below
commit ea928cee466a144fd06d7f75fcc318138c632bc1
Author: Devin Leamy <[email protected]>
AuthorDate: Wed Apr 24 13:05:38 2024 -0400
[cgroups2] Made `cgroups2::processes` optionally recursive.
Previously, `cgroups2::processes` could only fetch processes
from inside of the provided cgroup. We can now fetch all of
the processes inside of a cgroup subtree by passing an
(optional) `recursive` flag.
```c++
Try<std::set<pid_t>> processes(
const std::string& cgroup,
bool recursive = false);
```
This closes #570
---
src/linux/cgroups2.cpp | 41 +++++++++++++++++++++---------
src/linux/cgroups2.hpp | 6 ++++-
src/tests/containerizer/cgroups2_tests.cpp | 5 ++++
3 files changed, 39 insertions(+), 13 deletions(-)
diff --git a/src/linux/cgroups2.cpp b/src/linux/cgroups2.cpp
index f309d604d..ad282695e 100644
--- a/src/linux/cgroups2.cpp
+++ b/src/linux/cgroups2.cpp
@@ -462,29 +462,46 @@ Try<string> cgroup(pid_t pid)
}
-Try<set<pid_t>> processes(const string& cgroup)
+Try<set<pid_t>> processes(const string& cgroup, bool recursive)
{
if (!cgroups2::exists(cgroup)) {
return Error("Cgroup '" + cgroup + "' does not exist");
}
- Try<string> contents = cgroups2::read<string>(cgroup, control::PROCESSES);
- if (contents.isError()) {
- return Error(
- "Failed to read cgroup.procs in '" + cgroup + "': " +
contents.error());
+ set<string> cgroups = {cgroup};
+
+ if (recursive) {
+ Try<set<string>> descendants = cgroups2::get(cgroup);
+ if (descendants.isError()) {
+ return Error("Failed to list cgroups: " + descendants.error());
+ }
+ cgroups.insert(descendants->begin(), descendants->end());
}
set<pid_t> pids;
- foreach (const string& line, strings::split(*contents, "\n")) {
- if (line.empty()) continue;
- Try<pid_t> pid = numify<pid_t>(line);
- if (pid.isError()) {
- return Error(
- "Failed to parse line '" + line + "' as a pid: " + pid.error());
+ foreach (const string& cgroup, cgroups) {
+ Try<string> contents = cgroups2::read<string>(cgroup, control::PROCESSES);
+
+ if (contents.isError() && !exists(cgroup)) {
+ continue; // Ignore missing cgroups due to races.
+ }
+
+ if (contents.isError()) {
+ return Error("Failed to read cgroup.procs in '" + cgroup + "': "
+ + contents.error());
}
- pids.insert(*pid);
+ foreach (const string& line, strings::split(*contents, "\n")) {
+ if (line.empty()) continue;
+
+ Try<pid_t> pid = numify<pid_t>(line);
+ if (pid.isError()) {
+ return Error("Failed to parse '" + line + "' as a pid: " +
pid.error());
+ }
+
+ pids.insert(*pid);
+ }
}
return pids;
diff --git a/src/linux/cgroups2.hpp b/src/linux/cgroups2.hpp
index 7060573a4..2639e2f74 100644
--- a/src/linux/cgroups2.hpp
+++ b/src/linux/cgroups2.hpp
@@ -93,7 +93,11 @@ Try<std::string> cgroup(pid_t pid);
// Get the processes inside of a cgroup.
-Try<std::set<pid_t>> processes(const std::string& cgroup);
+//
+// Optionally fetch all of the processes in the cgroup subtree by setting
+// recursive=true. This will include all processes in nested cgroups.
+Try<std::set<pid_t>> processes(
+ const std::string& cgroup, bool recursive = false);
// Get the threads inside of a cgroup.
diff --git a/src/tests/containerizer/cgroups2_tests.cpp
b/src/tests/containerizer/cgroups2_tests.cpp
index 592c4bce6..918dfe4ef 100644
--- a/src/tests/containerizer/cgroups2_tests.cpp
+++ b/src/tests/containerizer/cgroups2_tests.cpp
@@ -185,6 +185,11 @@ TEST_F(Cgroups2Test, ROOT_CGROUPS2_AssignProcesses)
EXPECT_EQ(1u, pids->size());
EXPECT_EQ(pid, *pids->begin());
+ // Should fetch the `pid` from the nested `TEST_CGROUP` if `recursive=true`.
+ Try<set<pid_t>> root_pids = cgroups2::processes(cgroups2::ROOT_CGROUP, true);
+ EXPECT_SOME(pids);
+ EXPECT_EQ(1u, root_pids->count(pid));
+
// Kill the child process.
ASSERT_NE(-1, ::kill(pid, SIGKILL));
AWAIT_EXPECT_WTERMSIG_EQ(SIGKILL, process::reap(pid));