From 90f4c0473a70e83ace55c56bbc182fdd3c5c5944 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Wed, 3 Dec 2025 18:59:34 +0000 Subject: [PATCH] core: set Result=start-limit-hit when a unit is rate limited There is currently no way to figure out a rate limit was hit on a unit, as the last result is stripped in order to keep reporting the first result, which is useful in case of a watchdog failure, which is the reason why it was changed as such. But rate limiting is also an important information to provide to users, so allow the Result property to reflect it when it happens. --- src/core/automount.c | 2 +- src/core/mount.c | 2 +- src/core/path.c | 2 +- src/core/service.c | 2 +- src/core/socket.c | 2 +- src/core/swap.c | 2 +- src/core/timer.c | 2 +- test/units/TEST-07-PID1.issue-3166.sh | 1 + 8 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/core/automount.c b/src/core/automount.c index 05b35d06a4..6543204400 100644 --- a/src/core/automount.c +++ b/src/core/automount.c @@ -324,7 +324,7 @@ static void automount_dump(Unit *u, FILE *f, const char *prefix) { static void automount_enter_dead(Automount *a, AutomountResult f) { assert(a); - if (a->result == AUTOMOUNT_SUCCESS) + if (a->result == AUTOMOUNT_SUCCESS || IN_SET(f, AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT, AUTOMOUNT_FAILURE_START_LIMIT_HIT)) a->result = f; unit_log_result(UNIT(a), a->result == AUTOMOUNT_SUCCESS, automount_result_to_string(a->result)); diff --git a/src/core/mount.c b/src/core/mount.c index 833ab762cb..680e376feb 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -893,7 +893,7 @@ static int mount_spawn(Mount *m, ExecCommand *c, ExecFlags flags, PidRef *ret_pi static void mount_enter_dead(Mount *m, MountResult f, bool flush_result) { assert(m); - if (m->result == MOUNT_SUCCESS || flush_result) + if (m->result == MOUNT_SUCCESS || f == MOUNT_FAILURE_START_LIMIT_HIT || flush_result) m->result = f; unit_log_result(UNIT(m), m->result == MOUNT_SUCCESS, mount_result_to_string(m->result)); diff --git a/src/core/path.c b/src/core/path.c index 74218dd6be..764dea03dc 100644 --- a/src/core/path.c +++ b/src/core/path.c @@ -502,7 +502,7 @@ static int path_coldplug(Unit *u) { static void path_enter_dead(Path *p, PathResult f) { assert(p); - if (p->result == PATH_SUCCESS) + if (p->result == PATH_SUCCESS || IN_SET(f, PATH_FAILURE_START_LIMIT_HIT, PATH_FAILURE_UNIT_START_LIMIT_HIT)) p->result = f; unit_log_result(UNIT(p), p->result == PATH_SUCCESS, path_result_to_string(p->result)); diff --git a/src/core/service.c b/src/core/service.c index dcc4a992cc..9f7ccaaa41 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -2115,7 +2115,7 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) if (unit_stop_pending(UNIT(s))) allow_restart = false; - if (s->result == SERVICE_SUCCESS) + if (s->result == SERVICE_SUCCESS || f == SERVICE_FAILURE_START_LIMIT_HIT) s->result = f; if (s->result == SERVICE_SUCCESS) { diff --git a/src/core/socket.c b/src/core/socket.c index cb79c590aa..848cb31372 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -2116,7 +2116,7 @@ static int socket_chown(Socket *s, PidRef *ret_pid) { static void socket_enter_dead(Socket *s, SocketResult f) { assert(s); - if (s->result == SOCKET_SUCCESS) + if (s->result == SOCKET_SUCCESS || IN_SET(f, SOCKET_FAILURE_SERVICE_START_LIMIT_HIT, SOCKET_FAILURE_START_LIMIT_HIT)) s->result = f; if (s->result == SOCKET_SUCCESS) diff --git a/src/core/swap.c b/src/core/swap.c index 3ab4b134f2..5de1dccf42 100644 --- a/src/core/swap.c +++ b/src/core/swap.c @@ -668,7 +668,7 @@ static int swap_spawn(Swap *s, ExecCommand *c, PidRef *ret_pid) { static void swap_enter_dead(Swap *s, SwapResult f) { assert(s); - if (s->result == SWAP_SUCCESS) + if (s->result == SWAP_SUCCESS || f == SWAP_FAILURE_START_LIMIT_HIT) s->result = f; unit_log_result(UNIT(s), s->result == SWAP_SUCCESS, swap_result_to_string(s->result)); diff --git a/src/core/timer.c b/src/core/timer.c index d95514462d..f2d4b5cc3d 100644 --- a/src/core/timer.c +++ b/src/core/timer.c @@ -324,7 +324,7 @@ static int timer_coldplug(Unit *u) { static void timer_enter_dead(Timer *t, TimerResult f) { assert(t); - if (t->result == TIMER_SUCCESS) + if (t->result == TIMER_SUCCESS || f == TIMER_FAILURE_START_LIMIT_HIT) t->result = f; unit_log_result(UNIT(t), t->result == TIMER_SUCCESS, timer_result_to_string(t->result)); diff --git a/test/units/TEST-07-PID1.issue-3166.sh b/test/units/TEST-07-PID1.issue-3166.sh index 6677901358..07c211debe 100755 --- a/test/units/TEST-07-PID1.issue-3166.sh +++ b/test/units/TEST-07-PID1.issue-3166.sh @@ -14,3 +14,4 @@ while [[ "$active_state" == "activating" || "$active_state" =~ ^(in)?active$ ]]; done systemctl is-failed issue3166-fail-on-restart.service || exit 1 [[ "$(systemctl show --value --property NRestarts issue3166-fail-on-restart.service)" -le 3 ]] || exit 1 +[[ "$(systemctl show --value --property Result issue3166-fail-on-restart.service)" = "start-limit-hit" ]] || exit 1