Merge pull request #22183 from anitazha/oomdkillfix

oomd: fix potential race between killing cgroups and cleaning up cgroups
This commit is contained in:
Yu Watanabe
2022-01-21 09:44:12 +09:00
committed by GitHub
2 changed files with 20 additions and 10 deletions
+7 -3
View File
@@ -410,7 +410,7 @@ static int monitor_swap_contexts_handler(sd_event_source *s, uint64_t usec, void
if (r < 0)
log_notice_errno(r, "Failed to kill any cgroup(s) based on swap: %m");
else {
if (selected)
if (selected && r > 0)
log_notice("Killed %s due to memory used (%"PRIu64") / total (%"PRIu64") and "
"swap used (%"PRIu64") / total (%"PRIu64") being more than "
PERMYRIAD_AS_PERCENT_FORMAT_STR,
@@ -518,9 +518,13 @@ static int monitor_memory_pressure_contexts_handler(sd_event_source *s, uint64_t
if (r < 0)
log_notice_errno(r, "Failed to kill any cgroup(s) under %s based on pressure: %m", t->path);
else {
/* Don't act on all the high pressure cgroups at once; return as soon as we kill one */
/* Don't act on all the high pressure cgroups at once; return as soon as we kill one.
* If r == 0 then it means there were not eligible candidates, the candidate cgroup
* disappeared, or the candidate cgroup has no processes by the time we tried to kill
* it. In either case, go through the event loop again and select a new candidate if
* pressure is still high. */
m->mem_pressure_post_action_delay_start = usec_now;
if (selected)
if (selected && r > 0)
log_notice("Killed %s due to memory pressure for %s being %lu.%02lu%% > %lu.%02lu%%"
" for > %s with reclaim activity",
selected, t->path,
+13 -7
View File
@@ -196,9 +196,19 @@ int oomd_cgroup_kill(const char *path, bool recurse, bool dry_run) {
r = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, path, SIGKILL, CGROUP_IGNORE_SELF, pids_killed, log_kill, NULL);
else
r = cg_kill(SYSTEMD_CGROUP_CONTROLLER, path, SIGKILL, CGROUP_IGNORE_SELF, pids_killed, log_kill, NULL);
if (r < 0)
/* The cgroup could have been cleaned up after we have sent SIGKILL to all of the processes, but before
* we could do one last iteration of cgroup.procs to check. Or the service unit could have exited and
* was removed between picking candidates and coming into this function. In either case, let's log
* about it let the caller decide what to do once they know how many PIDs were killed. */
if (IN_SET(r, -ENOENT, -ENODEV))
log_debug_errno(r, "Error when sending SIGKILL to processes in cgroup path %s, ignoring: %m", path);
else if (r < 0)
return r;
if (set_isempty(pids_killed))
log_debug("Nothing killed when attempting to kill %s", path);
r = increment_oomd_xattr(path, "user.oomd_kill", set_size(pids_killed));
if (r < 0)
log_debug_errno(r, "Failed to set user.oomd_kill on kill: %m");
@@ -224,8 +234,6 @@ int oomd_kill_by_pgscan_rate(Hashmap *h, const char *prefix, bool dry_run, char
continue;
r = oomd_cgroup_kill(sorted[i]->path, true, dry_run);
if (r == 0)
continue; /* We didn't find anything to kill */
if (r == -ENOMEM)
return r; /* Treat oom as a hard error */
if (r < 0) {
@@ -238,7 +246,7 @@ int oomd_kill_by_pgscan_rate(Hashmap *h, const char *prefix, bool dry_run, char
if (!selected)
return -ENOMEM;
*ret_selected = selected;
return 1;
return r;
}
return ret;
@@ -264,8 +272,6 @@ int oomd_kill_by_swap_usage(Hashmap *h, uint64_t threshold_usage, bool dry_run,
continue;
r = oomd_cgroup_kill(sorted[i]->path, true, dry_run);
if (r == 0)
continue; /* We didn't find anything to kill */
if (r == -ENOMEM)
return r; /* Treat oom as a hard error */
if (r < 0) {
@@ -278,7 +284,7 @@ int oomd_kill_by_swap_usage(Hashmap *h, uint64_t threshold_usage, bool dry_run,
if (!selected)
return -ENOMEM;
*ret_selected = selected;
return 1;
return r;
}
return ret;