diff --git a/src/oom/oomd-manager.c b/src/oom/oomd-manager.c index 3898ab707c..1ab7099d2e 100644 --- a/src/oom/oomd-manager.c +++ b/src/oom/oomd-manager.c @@ -541,9 +541,8 @@ static int monitor_memory_pressure_contexts_handler(sd_event_source *s, uint64_t log_error_errno(r, "Failed to select any cgroups under %s based on pressure, ignoring: %m", t->path); else { /* 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 + * If r == 0 then the cgroup is already queued for kill by an earlier iteration. + * 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 && r > 0) { diff --git a/src/oom/oomd-util.c b/src/oom/oomd-util.c index fb4b58eaf5..8167e10a8b 100644 --- a/src/oom/oomd-util.c +++ b/src/oom/oomd-util.c @@ -494,12 +494,20 @@ int oomd_cgroup_kill_mark(Manager *m, OomdCGroupContext *ctx) { r = set_ensure_put(&m->kill_states, &oomd_kill_state_hash_ops, ks); if (r < 0) return log_oom_debug(); + if (r == 0) { + /* The cgroup is already queued. Drop only this temporary object, because running the normal + * cleanup path would remove by cgroup path key and could interfere with the existing queued + * kill state. */ + oomd_cgroup_context_unref(ks->ctx); + ks = mfree(ks); + return 0; + } r = oomd_prekill_hook(m, ks); if (r < 0) log_warning_errno(r, "oomd prekill hook failed for %s, ignoring: %m", ctx->path); - return 0; + return 1; } typedef void (*dump_candidate_func)(const OomdCGroupContext *ctx, FILE *f, const char *prefix);