diff --git a/src/oomd/plugins/BaseKillPlugin.cpp b/src/oomd/plugins/BaseKillPlugin.cpp index e02d268f..2583fd6d 100644 --- a/src/oomd/plugins/BaseKillPlugin.cpp +++ b/src/oomd/plugins/BaseKillPlugin.cpp @@ -564,14 +564,20 @@ int BaseKillPlugin::tryToKillCgroup( } auto procsBeforeKill = Fs::readPidsCurrentAt(target.fd()); - if (!procsBeforeKill) { - OLOG << "Failed to read pids from " << target.cgroup().absolutePath() - << ", skip killing cgroup"; - } else if (*procsBeforeKill == 0) { + auto populated = Fs::readIsPopulatedAt(target.fd()); + + if (!populated) { + OLOG << "Failed to read cgroup.events in " + << target.cgroup().absolutePath() + << ", something is wrong. Skip killing cgroup."; + } else if (!populated.value()) { OLOG << "No pids in " << target.cgroup().absolutePath() << ", skip killing cgroup"; } else if (kernelKillCgroup(target)) { OLOG << "Failed to kill cgroup " << target.cgroup().absolutePath(); + } else if (!procsBeforeKill || procsBeforeKill.value() == 0) { + // Placeholder if we cannot figure out how many we actually killed + nrKilled = 1; } else { nrKilled = procsBeforeKill.value(); } diff --git a/src/oomd/plugins/CorePluginsTest.cpp b/src/oomd/plugins/CorePluginsTest.cpp index b2b4f54a..9a5da270 100644 --- a/src/oomd/plugins/CorePluginsTest.cpp +++ b/src/oomd/plugins/CorePluginsTest.cpp @@ -714,7 +714,8 @@ TEST_F(DoubleKillTest, KillsTwice) { tempdir_, {F::makeDir( "A", - {F::makeFile("pids.current", "1\n"), + {F::makeFile("cgroup.events", "populated 1"), + F::makeFile("pids.current", "1\n"), F::makeFile("cgroup.kill", "0")})})); // Should do nothing, since it will write to cgroup.kill with no side effect. @@ -734,6 +735,28 @@ TEST_F(DoubleKillTest, KillsTwice) { EXPECT_EQ(plugin->run(ctx_), Engine::PluginRet::STOP); } +class NoPidControllerTest : public CorePluginsTest {}; + +TEST_F(NoPidControllerTest, KillsWithoutPidController) { + // Despite not having a pid controller, we should still be able to kill + F::materialize(F::makeDir( + tempdir_, + {F::makeDir( + "A", + {F::makeFile("cgroup.kill", "0"), + F::makeFile("cgroup.events", "populated 1")})})); + auto plugin = std::make_shared(); + ASSERT_NE(plugin, nullptr); + const PluginConstructionContext compile_context(tempdir_); + Engine::PluginArgs args; + args["cgroup"] = "*"; + args["recursive"] = "true"; + args["kernelkill"] = "true"; + + ASSERT_EQ(plugin->init(args, compile_context), 0); + EXPECT_EQ(plugin->run(ctx_), Engine::PluginRet::STOP); +} + class PressureRisingBeyondTest : public CorePluginsTest {}; TEST_F(PressureRisingBeyondTest, DetectsHighMemPressure) {