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 756b7d7ff [cgroups2] Introduced API to kill the processes inside of
cgroup subtree.
756b7d7ff is described below
commit 756b7d7ff9465cdf5758584e864a5b0444b14e16
Author: Devin Leamy <[email protected]>
AuthorDate: Fri Apr 5 17:14:28 2024 -0400
[cgroups2] Introduced API to kill the processes inside of cgroup subtree.
Introduces
```
cgroups2::kill(cgroup)
```
which will recursively kill all of the cgroups in a subtree.
We additionally update `cgroups::destroy` to use `cgroups::kill` such that
it now completely destroys a cgroup (i.e. all directories processes).
This closes #550
---
src/linux/cgroups2.cpp | 38 ++++++++++++++++++++++++++----
src/linux/cgroups2.hpp | 9 +++++--
src/tests/containerizer/cgroups2_tests.cpp | 6 -----
3 files changed, 41 insertions(+), 12 deletions(-)
diff --git a/src/linux/cgroups2.cpp b/src/linux/cgroups2.cpp
index 8b401a178..b5e4babe9 100644
--- a/src/linux/cgroups2.cpp
+++ b/src/linux/cgroups2.cpp
@@ -360,16 +360,46 @@ Try<Nothing> create(const string& cgroup, bool recursive)
}
+Try<Nothing> kill(const std::string& cgroup)
+{
+ if (!cgroups2::exists(cgroup)) {
+ return Error("Cgroup does not exist");
+ }
+
+ return cgroups2::write(cgroup, cgroups2::control::KILL, "1");
+}
+
+
Try<Nothing> destroy(const string& cgroup)
{
if (!cgroups2::exists(cgroup)) {
return Error("Cgroup '" + cgroup + "' does not exist");
}
- const string path = cgroups2::path(cgroup);
- Try<Nothing> rmdir = os::rmdir(path, false);
- if (rmdir.isError()) {
- return Error("Failed to remove directory '" + path + "': " +
rmdir.error());
+ // To destroy a subtree of cgroups we first kill all of the processes inside
+ // of the cgroup and then remove all of the cgroup directories, removing
+ // the most deeply nested directories first.
+ Try<Nothing> kill = cgroups2::kill(cgroup);
+ if (kill.isError()) {
+ return Error("Failed to kill processes in cgroup");
+ }
+
+ Try<set<string>> cgroups = cgroups2::get(cgroup);
+ if (cgroups.isError()) {
+ return Error("Failed to get nested cgroups: " + cgroups.error());
+ }
+
+ vector<string> sorted(cgroups->begin(), cgroups->end());
+ sorted.push_back(cgroup);
+ std::sort(sorted.rbegin(), sorted.rend());
+
+ foreach (const string& cgroup, sorted) {
+ const string& path = cgroups2::path(cgroup);
+ Try<Nothing> rmdir = os::rmdir(path, false);
+ if (rmdir.isError()) {
+ return Error(
+ "Failed to remove directory '" + path + "': " + rmdir.error());
+ }
}
return Nothing();
diff --git a/src/linux/cgroups2.hpp b/src/linux/cgroups2.hpp
index 3a31ca0da..e4f482405 100644
--- a/src/linux/cgroups2.hpp
+++ b/src/linux/cgroups2.hpp
@@ -69,8 +69,13 @@ Try<std::set<std::string>> get(const std::string& cgroup =
ROOT_CGROUP);
Try<Nothing> create(const std::string& cgroup, bool recursive = false);
-// Destroy a cgroup. If the cgroup does not exist or cannot be destroyed,
-// e.g. because it contains processes, an error is returned.
+// Recursively kill all of the processes inside of a cgroup and all child
+// cgroups with SIGKILL.
+Try<Nothing> kill(const std::string& cgroup);
+
+
+// Recursively destroy a cgroup and all nested cgroups. Processes inside of
+// destroyed cgroups are killed with SIGKILL.
Try<Nothing> destroy(const std::string& cgroup);
diff --git a/src/tests/containerizer/cgroups2_tests.cpp
b/src/tests/containerizer/cgroups2_tests.cpp
index cddf2e428..5c0a3e7b2 100644
--- a/src/tests/containerizer/cgroups2_tests.cpp
+++ b/src/tests/containerizer/cgroups2_tests.cpp
@@ -360,12 +360,6 @@ TEST_F(Cgroups2Test, ROOT_CGROUPS2_GetCgroups)
path::join(TEST_CGROUP, "test1/b/c")
}),
cgroups2::get(path::join(TEST_CGROUP, "test1/b")));
-
- // Destroy the cgroups in reverse order so the most deeply-nested cgroups
- // are removed first.
- for (int i = cgroups.size() - 1; i >= 0; --i) {
- ASSERT_SOME(cgroups2::destroy(cgroups[i]));
- }
}