]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
run: Ref() the unit again after reconnecting to the bus
authorMike Yuan <me@yhndnzj.com>
Mon, 17 Mar 2025 19:08:51 +0000 (20:08 +0100)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 18 Mar 2025 00:23:44 +0000 (09:23 +0900)
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.

src/run/run.c

index b9a4ecd2e4f042a66a0efa52aafffda116d3612f..cdb5cfefd629371c22406b524eec640c8c74f76c 100644 (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");
-
-                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);
                 }