run: Ref() the unit again after reconnecting to the bus

Follow-up for c8f59296bf

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.
This commit is contained in:
Mike Yuan
2025-03-18 09:23:44 +09:00
committed by Yu Watanabe
parent 8e29a5b9b3
commit 2b983b43c6
+46 -17
View File
@@ -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");
/* 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;
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");
}
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);
}