From ec9fd0d4f5f77404fbfabde9e7a9d01aaa1356ff Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Wed, 9 Oct 2024 16:37:06 +0200 Subject: [PATCH] update-utmp: Make reconnect logic more robust We might also fail to connect to the private manager bus itself if the daemon-reexec is still ongoing, so let's handle that as well by retrying on ECONNREFUSED. --- src/update-utmp/update-utmp.c | 45 +++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/src/update-utmp/update-utmp.c b/src/update-utmp/update-utmp.c index c376676e8d0..7a8a53f7e8e 100644 --- a/src/update-utmp/update-utmp.c +++ b/src/update-utmp/update-utmp.c @@ -82,6 +82,25 @@ static int get_current_runlevel(Context *c) { assert(c); for (unsigned n_attempts = 0;;) { + if (n_attempts++ > 0) { + /* systemd might have dropped off momentarily, let's not make this an error, + * and wait some random time. Let's pick a random time in the range 0ms…250ms, + * linearly scaled by the number of failed attempts. */ + c->bus = sd_bus_flush_close_unref(c->bus); + + usec_t usec = random_u64_range(UINT64_C(10) * USEC_PER_MSEC + + UINT64_C(240) * USEC_PER_MSEC * n_attempts/64); + (void) usleep_safe(usec); + + r = bus_connect_system_systemd(&c->bus); + if (r == -ECONNREFUSED && n_attempts < 64) { + log_debug_errno(r, "Failed to reconnect to system bus, retrying after a slight delay: %m"); + continue; + } + if (r < 0) + return log_error_errno(r, "Failed to reconnect to system bus: %m"); + } + FOREACH_ELEMENT(e, table) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_free_ char *state = NULL, *path = NULL; @@ -102,18 +121,10 @@ static int get_current_runlevel(Context *c) { sd_bus_error_has_names(&error, SD_BUS_ERROR_NO_REPLY, SD_BUS_ERROR_DISCONNECTED)) && - ++n_attempts < 64) { - - /* systemd might have dropped off momentarily, let's not make this an error, - * and wait some random time. Let's pick a random time in the range 0ms…250ms, - * linearly scaled by the number of failed attempts. */ - - usec_t usec = random_u64_range(UINT64_C(10) * USEC_PER_MSEC + - UINT64_C(240) * USEC_PER_MSEC * n_attempts/64); - log_debug_errno(r, "Failed to get state of %s, retrying after %s: %s", - e->special, FORMAT_TIMESPAN(usec, USEC_PER_MSEC), bus_error_message(&error, r)); - (void) usleep_safe(usec); - goto reconnect; + n_attempts < 64) { + log_debug_errno(r, "Failed to get state of %s, retrying after a slight delay: %s", + e->special, bus_error_message(&error, r)); + break; } if (r < 0) return log_warning_errno(r, "Failed to get state of %s: %s", e->special, bus_error_message(&error, r)); @@ -121,14 +132,8 @@ static int get_current_runlevel(Context *c) { if (STR_IN_SET(state, "active", "reloading")) return e->runlevel; } - - return 0; - -reconnect: - c->bus = sd_bus_flush_close_unref(c->bus); - r = bus_connect_system_systemd(&c->bus); - if (r < 0) - return log_error_errno(r, "Failed to reconnect to system bus: %m"); + if (r >= 0) + return 0; } } -- 2.47.3