oomd: Fix Killed signal reason being lost

Emitting "oom" doesn't mesh with the org.freedesktop.oom1.Manager
Killed() API contract, which defines "memory-used" and "memory-pressure"
as possible reasons. Consumers that key off reason thus will either lose
policy attribution or may reject the unknown value completely.

Plumb the reason through so it is visible to consumers.
This commit is contained in:
Chris Down
2026-02-17 14:50:17 +09:00
committed by Yu Watanabe
parent 4e40c2a515
commit 936d864b0b
4 changed files with 17 additions and 9 deletions
+2 -2
View File
@@ -416,7 +416,7 @@ static int monitor_swap_contexts_handler(sd_event_source *s, uint64_t usec, void
return 0;
}
r = oomd_cgroup_kill_mark(m, selected);
r = oomd_cgroup_kill_mark(m, selected, "memory-used");
if (r == -ENOMEM)
return log_oom();
if (r < 0)
@@ -534,7 +534,7 @@ static int monitor_memory_pressure_contexts_handler(sd_event_source *s, uint64_t
return 0;
}
r = oomd_cgroup_kill_mark(m, selected);
r = oomd_cgroup_kill_mark(m, selected, "memory-pressure");
if (r == -ENOMEM)
return log_oom();
if (r < 0)
+8 -4
View File
@@ -27,6 +27,7 @@
typedef struct OomdKillState {
Manager *manager;
OomdCGroupContext *ctx;
const char *reason;
/* This holds sd_varlink references */
Set *links;
} OomdKillState;
@@ -245,11 +246,12 @@ int oomd_sort_cgroup_contexts(Hashmap *h, oomd_compare_t compare_func, const cha
return (int) k;
}
int oomd_cgroup_kill(Manager *m, OomdCGroupContext *ctx, bool recurse) {
int oomd_cgroup_kill(Manager *m, OomdCGroupContext *ctx, bool recurse, const char *reason) {
_cleanup_set_free_ Set *pids_killed = NULL;
int r;
assert(ctx);
assert(!m || reason);
pids_killed = set_new(NULL);
if (!pids_killed)
@@ -288,7 +290,7 @@ int oomd_cgroup_kill(Manager *m, OomdCGroupContext *ctx, bool recurse) {
"Killed",
"ss",
ctx->path,
"oom");
reason);
return !set_isempty(pids_killed);
}
@@ -334,7 +336,7 @@ static void oomd_kill_state_remove(OomdKillState *ks) {
if (!set_isempty(ks->links))
return;
r = oomd_cgroup_kill(ks->manager, ks->ctx, /* recurse= */ true);
r = oomd_cgroup_kill(ks->manager, ks->ctx, /* recurse= */ true, ks->reason);
if (r < 0)
log_debug_errno(r, "Failed to kill cgroup '%s', ignoring: %m", ks->ctx->path);
oomd_kill_state_free(ks);
@@ -465,11 +467,12 @@ static int oomd_prekill_hook(Manager *m, OomdKillState *ks) {
return 0;
}
int oomd_cgroup_kill_mark(Manager *m, OomdCGroupContext *ctx) {
int oomd_cgroup_kill_mark(Manager *m, OomdCGroupContext *ctx, const char *reason) {
int r;
assert(ctx);
assert(m);
assert(reason);
if (m->dry_run) {
_cleanup_free_ char *cg_path = NULL;
@@ -489,6 +492,7 @@ int oomd_cgroup_kill_mark(Manager *m, OomdCGroupContext *ctx) {
*ks = (OomdKillState) {
.manager = m,
.ctx = oomd_cgroup_context_ref(ctx),
.reason = reason,
};
r = set_ensure_put(&m->kill_states, &oomd_kill_state_hash_ops, ks);
+2 -2
View File
@@ -124,8 +124,8 @@ int oomd_sort_cgroup_contexts(Hashmap *h, oomd_compare_t compare_func, const cha
int oomd_fetch_cgroup_oom_preference(OomdCGroupContext *ctx, const char *prefix);
/* Returns a negative value on error, 0 if no processes were killed, or 1 if processes were killed. */
int oomd_cgroup_kill(Manager *m, OomdCGroupContext *ctx, bool recurse);
int oomd_cgroup_kill_mark(Manager *m, OomdCGroupContext *ctx);
int oomd_cgroup_kill(Manager *m, OomdCGroupContext *ctx, bool recurse, const char *reason);
int oomd_cgroup_kill_mark(Manager *m, OomdCGroupContext *ctx, const char *reason);
/* The following oomd_kill_by_* functions return 1 if processes were killed, or negative otherwise. */
/* If `prefix` is supplied, only cgroups whose paths start with `prefix` are eligible candidates. Otherwise,
+5 -1
View File
@@ -88,7 +88,11 @@ TEST(oomd_cgroup_kill) {
ASSERT_OK(fork_and_sleep(5, &two));
ASSERT_OK(cg_attach(subcgroup, two.pid));
ASSERT_OK_POSITIVE(oomd_cgroup_kill(NULL /* manager */, &(OomdCGroupContext){ .path = subcgroup }, false /* recurse */));
ASSERT_OK_POSITIVE(oomd_cgroup_kill(
/* m= */ NULL,
&(OomdCGroupContext){ .path = subcgroup },
/* recurse= */ false,
/* reason= */ NULL));
ASSERT_OK(cg_get_xattr(subcgroup, "user.oomd_ooms", &v, /* ret_size= */ NULL));
ASSERT_STREQ(v, i == 0 ? "1" : "2");