From 9cf6ad16dd35a95af926f55ccfc9842311d485c3 Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Fri, 12 Sep 2025 14:14:26 +0200 Subject: [PATCH] core: Expose oom kills and managed oom kills as properties It can be useful for users to know this information so let's expose it as properties so it can be queried. --- man/org.freedesktop.systemd1.xml | 69 ++++++++++++++++++++++++++++ src/core/dbus-unit.c | 38 +++++++++++++++ src/core/varlink-cgroup.c | 6 ++- src/shared/varlink-io.systemd.Unit.c | 8 +++- test/units/TEST-55-OOMD.sh | 2 + 5 files changed, 121 insertions(+), 2 deletions(-) diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml index ed227127489..2b30adab9b4 100644 --- a/man/org.freedesktop.systemd1.xml +++ b/man/org.freedesktop.systemd1.xml @@ -2691,6 +2691,15 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { or the restart rate limit is reached. See the RestartMode= section in systemd.service5 for more details. + + OOMKills contains a different value depending on whether + OOMPolicy=kill is enabled for the unit or not. If enabled, the property contains the + number of times the kernel OOM killer killed all the processes in the unit's cgroup and its + descendant cgroups. If disabled, the property contains the number of processes the kernel OOM killer + has killed in the unit's cgroup and its descendant cgroups. + + ManagedOOMKills contains the number of times systemd-oomd + killed all the processes in the unit's cgroup and its descendant cgroups. @@ -2900,6 +2909,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly t IOWriteOperations = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t OOMKills = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t ManagedOOMKills = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly b Delegate = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly as DelegateControllers = ['...', ...]; @@ -4247,6 +4260,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { + + + + @@ -5139,6 +5156,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly t IOWriteOperations = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t OOMKills = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t ManagedOOMKills = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly b Delegate = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly as DelegateControllers = ['...', ...]; @@ -6486,6 +6507,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { + + + + @@ -7202,6 +7227,10 @@ node /org/freedesktop/systemd1/unit/home_2emount { @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly t IOWriteOperations = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t OOMKills = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t ManagedOOMKills = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly b Delegate = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly as DelegateControllers = ['...', ...]; @@ -8379,6 +8408,10 @@ node /org/freedesktop/systemd1/unit/home_2emount { + + + + @@ -9228,6 +9261,10 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly t IOWriteOperations = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t OOMKills = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t ManagedOOMKills = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly b Delegate = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly as DelegateControllers = ['...', ...]; @@ -10369,6 +10406,10 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { + + + + @@ -11071,6 +11112,10 @@ node /org/freedesktop/systemd1/unit/system_2eslice { @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly t IOWriteOperations = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t OOMKills = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t ManagedOOMKills = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly b Delegate = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly as DelegateControllers = ['...', ...]; @@ -11436,6 +11481,10 @@ node /org/freedesktop/systemd1/unit/system_2eslice { + + + + @@ -11647,6 +11696,10 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope { @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly t IOWriteOperations = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t OOMKills = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") + readonly t ManagedOOMKills = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly b Delegate = ...; @org.freedesktop.DBus.Property.EmitsChangedSignal("false") readonly as DelegateControllers = ['...', ...]; @@ -12050,6 +12103,10 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope { + + + + @@ -12459,6 +12516,8 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \ LogsDirectoryQuotaUsage, LogsDirectoryAccounting, and KillSubgroup() were added in version 258. + OOMKills, and + ManagedOOMKills were added in 259. Socket Unit Objects @@ -12524,6 +12583,8 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \ LogsDirectoryQuotaUsage, LogsDirectoryAccounting, and KillSubgroup() were added in version 258. + OOMKills, and + ManagedOOMKills were added in 259. Mount Unit Objects @@ -12584,6 +12645,8 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \ LogsDirectoryQuotaUsage, LogsDirectoryAccounting, and KillSubgroup() were added in version 258. + OOMKills, and + ManagedOOMKills were added in 259. Swap Unit Objects @@ -12642,6 +12705,8 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \ LogsDirectoryQuotaUsage, LogsDirectoryAccounting, and KillSubgroup() were added in version 258. + OOMKills, and + ManagedOOMKills were added in 259. Slice Unit Objects @@ -12672,6 +12737,8 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \ NCurrentlyActive, RemoveSubgroup(), and KillSubgroup() were added in version 258. + OOMKills, and + ManagedOOMKills were added in 259. Scope Unit Objects @@ -12700,6 +12767,8 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \ ManagedOOMMemoryPressureDurationUSec was added in version 257. RemoveSubgroup() and KillSubgroup() were added in version 258. + OOMKills, and + ManagedOOMKills were added in 259. Job Objects diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index cf015b5a7bc..a524cfad22c 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -1295,6 +1295,42 @@ static int property_get_cgroup_id( return sd_bus_message_append(reply, "t", crt ? crt->cgroup_id : UINT64_C(0)); } +static int property_get_oom_kills( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Unit *u = ASSERT_PTR(userdata); + + assert(bus); + assert(reply); + + CGroupRuntime *crt = unit_get_cgroup_runtime(u); + return sd_bus_message_append(reply, "t", crt ? crt->oom_kill_last : UINT64_MAX); +} + +static int property_get_managed_oom_kills( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Unit *u = ASSERT_PTR(userdata); + + assert(bus); + assert(reply); + + CGroupRuntime *crt = unit_get_cgroup_runtime(u); + return sd_bus_message_append(reply, "t", crt ? crt->managed_oom_kill_last : UINT64_MAX); +} + static int append_process(sd_bus_message *reply, const char *p, PidRef *pid, Set *pids) { _cleanup_free_ char *buf = NULL, *cmdline = NULL; int r; @@ -1715,6 +1751,8 @@ const sd_bus_vtable bus_unit_cgroup_vtable[] = { SD_BUS_PROPERTY("IOReadOperations", "t", property_get_io_counter, 0, 0), SD_BUS_PROPERTY("IOWriteBytes", "t", property_get_io_counter, 0, 0), SD_BUS_PROPERTY("IOWriteOperations", "t", property_get_io_counter, 0, 0), + SD_BUS_PROPERTY("OOMKills", "t", property_get_oom_kills, 0, 0), + SD_BUS_PROPERTY("ManagedOOMKills", "t", property_get_managed_oom_kills, 0, 0), SD_BUS_METHOD_WITH_ARGS("GetProcesses", SD_BUS_NO_ARGS, diff --git a/src/core/varlink-cgroup.c b/src/core/varlink-cgroup.c index 88d13f3c45b..7e23d4a0f7a 100644 --- a/src/core/varlink-cgroup.c +++ b/src/core/varlink-cgroup.c @@ -615,5 +615,9 @@ int unit_cgroup_runtime_build_json(sd_json_variant **ret, const char *name, void JSON_BUILD_PAIR_CALLBACK_NON_NULL("IOReadBytes", get_io_counter_build_json, u), JSON_BUILD_PAIR_CALLBACK_NON_NULL("IOReadOperations", get_io_counter_build_json, u), JSON_BUILD_PAIR_CALLBACK_NON_NULL("IOWriteBytes", get_io_counter_build_json, u), - JSON_BUILD_PAIR_CALLBACK_NON_NULL("IOWriteOperations", get_io_counter_build_json, u)); + JSON_BUILD_PAIR_CALLBACK_NON_NULL("IOWriteOperations", get_io_counter_build_json, u), + + /* OOM */ + SD_JSON_BUILD_PAIR_UNSIGNED("OOMKills", crt->oom_kill_last), + SD_JSON_BUILD_PAIR_UNSIGNED("ManagedOOMKills", crt->managed_oom_kill_last)); } diff --git a/src/shared/varlink-io.systemd.Unit.c b/src/shared/varlink-io.systemd.Unit.c index 30d5d8cd574..32c72f0040c 100644 --- a/src/shared/varlink-io.systemd.Unit.c +++ b/src/shared/varlink-io.systemd.Unit.c @@ -455,7 +455,13 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( SD_VARLINK_FIELD_COMMENT("The total number of bytes written to block devices by the cgroup"), SD_VARLINK_DEFINE_FIELD(IOWriteBytes, SD_VARLINK_INT, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("The total number of write operations performed on block devices by the cgroup"), - SD_VARLINK_DEFINE_FIELD(IOWriteOperations, SD_VARLINK_INT, SD_VARLINK_NULLABLE)); + SD_VARLINK_DEFINE_FIELD(IOWriteOperations, SD_VARLINK_INT, SD_VARLINK_NULLABLE), + + /* OOM */ + SD_VARLINK_FIELD_COMMENT("The number of processes of this unit killed by the kernel OOM killer"), + SD_VARLINK_DEFINE_FIELD(OOMKills, SD_VARLINK_INT, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("The number of processes of this unit killed by systemd-oomd"), + SD_VARLINK_DEFINE_FIELD(ManagedOOMKills, SD_VARLINK_INT, SD_VARLINK_NULLABLE)); static SD_VARLINK_DEFINE_STRUCT_TYPE( UnitRuntime, diff --git a/test/units/TEST-55-OOMD.sh b/test/units/TEST-55-OOMD.sh index 66793378584..ae0081063c3 100755 --- a/test/units/TEST-55-OOMD.sh +++ b/test/units/TEST-55-OOMD.sh @@ -125,6 +125,8 @@ test_basic() { if systemctl "$@" status TEST-55-OOMD-testbloat.service; then exit 42; fi if ! systemctl "$@" status TEST-55-OOMD-testchill.service; then exit 24; fi + assert_eq "$(systemctl "$@" show TEST-55-OOMD-testbloat.service -P ManagedOOMKills)" "1" + systemctl "$@" kill --signal=KILL TEST-55-OOMD-testbloat.service || : systemctl "$@" stop TEST-55-OOMD-testbloat.service systemctl "$@" stop TEST-55-OOMD-testchill.service -- 2.47.3