From: Mike Yuan Date: Mon, 17 Mar 2025 19:08:51 +0000 (+0100) Subject: run: Ref() the unit again after reconnecting to the bus X-Git-Tag: v258-rc1~1061 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2b983b43c6e4a0dc9d58671eaf2f508a8ce8e3b9;p=thirdparty%2Fsystemd.git run: Ref() the unit again after reconnecting to the bus Follow-up for c8f59296bff1ac1085c9073159ccaf8a333c5027 Currently, the unit is only reffed in transient_unit_set_properties() via AddRef(), which however would be dropped if a reconnection is attempted. Make sure to explicitly re-add reference in that case. --- diff --git a/src/run/run.c b/src/run/run.c index b9a4ecd2e4f..cdb5cfefd62 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -1646,32 +1646,42 @@ static int on_retry_timer(sd_event_source *s, uint64_t usec, void *userdata) { } static int run_context_reconnect(RunContext *c) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; int r; assert(c); run_context_detach_bus(c); - _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; r = connect_bus(&bus); + if (r < 0) + goto retry_timer; + + r = sd_bus_call_method(bus, + "org.freedesktop.systemd1", + c->bus_path, + "org.freedesktop.systemd1.Unit", + "Ref", + &error, + /* reply = */ NULL, NULL); if (r < 0) { - log_warning_errno(r, "Failed to reconnect, retrying in 2s: %m"); - - r = event_reset_time_relative( - c->event, - &c->retry_timer, - CLOCK_MONOTONIC, - 2 * USEC_PER_SEC, /* accuracy= */ 0, - on_retry_timer, c, - SD_EVENT_PRIORITY_NORMAL, - "retry-timeout", - /* force_reset= */ false); - if (r < 0) { - (void) sd_event_exit(c->event, EXIT_FAILURE); - return log_error_errno(r, "Failed to install retry timer: %m"); - } + /* Hmm, the service manager probably hasn't finished reexecution just yet? Try again later. */ + if (sd_bus_error_has_names(&error, + SD_BUS_ERROR_NO_REPLY, + SD_BUS_ERROR_DISCONNECTED, + SD_BUS_ERROR_TIMED_OUT, + SD_BUS_ERROR_SERVICE_UNKNOWN, + SD_BUS_ERROR_NAME_HAS_NO_OWNER)) + goto retry_timer; + + if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT)) + log_warning_errno(r, "Unit deactivated during reconnection to the bus, exiting."); + else + log_error_errno(r, "Failed to re-add reference to unit: %s", bus_error_message(&error, r)); - return 0; + (void) sd_event_exit(c->event, EXIT_FAILURE); + return r; } r = run_context_attach_bus(c, bus); @@ -1683,6 +1693,25 @@ static int run_context_reconnect(RunContext *c) { log_info("Reconnected to bus."); return run_context_update(c); + +retry_timer: + log_warning_errno(r, "Failed to reconnect, retrying in 2s: %m"); + + r = event_reset_time_relative( + c->event, + &c->retry_timer, + CLOCK_MONOTONIC, + 2 * USEC_PER_SEC, /* accuracy= */ 0, + on_retry_timer, c, + SD_EVENT_PRIORITY_NORMAL, + "retry-timeout", + /* force_reset= */ false); + if (r < 0) { + (void) sd_event_exit(c->event, EXIT_FAILURE); + return log_error_errno(r, "Failed to install retry timer: %m"); + } + + return 0; } static int run_context_check_started(RunContext *c) { @@ -1792,7 +1821,7 @@ static int run_context_update(RunContext *c) { SD_BUS_ERROR_SERVICE_UNKNOWN, SD_BUS_ERROR_NAME_HAS_NO_OWNER)) { - log_info("Bus call failed due to connection problems. Trying to reconnect..."); + log_info_errno(r, "Bus call failed due to connection problems. Trying to reconnect..."); /* Not propagating error, because we handled it already, by reconnecting. */ return run_context_reconnect(c); }