]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/core/busname.c
core: add "invocation ID" concept to service manager
[thirdparty/systemd.git] / src / core / busname.c
index 3592f72fe5f46b3041ea6710856dd45638bd99b7..63c7dde0bd9f23b4924a285b98c537585610296a 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -112,29 +110,27 @@ static void busname_done(Unit *u) {
         n->timer_event_source = sd_event_source_unref(n->timer_event_source);
 }
 
-static int busname_arm_timer(BusName *n) {
+static int busname_arm_timer(BusName *n, usec_t usec) {
         int r;
 
         assert(n);
 
-        if (n->timeout_usec <= 0) {
-                n->timer_event_source = sd_event_source_unref(n->timer_event_source);
-                return 0;
-        }
-
         if (n->timer_event_source) {
-                r = sd_event_source_set_time(n->timer_event_source, now(CLOCK_MONOTONIC) + n->timeout_usec);
+                r = sd_event_source_set_time(n->timer_event_source, usec);
                 if (r < 0)
                         return r;
 
                 return sd_event_source_set_enabled(n->timer_event_source, SD_EVENT_ONESHOT);
         }
 
+        if (usec == USEC_INFINITY)
+                return 0;
+
         r = sd_event_add_time(
                         UNIT(n)->manager->event,
                         &n->timer_event_source,
                         CLOCK_MONOTONIC,
-                        now(CLOCK_MONOTONIC) + n->timeout_usec, 0,
+                        usec, 0,
                         busname_dispatch_timer, n);
         if (r < 0)
                 return r;
@@ -153,7 +149,7 @@ static int busname_add_default_default_dependencies(BusName *n) {
         if (r < 0)
                 return r;
 
-        if (UNIT(n)->manager->running_as == MANAGER_SYSTEM) {
+        if (MANAGER_IS_SYSTEM(UNIT(n)->manager)) {
                 r = unit_add_two_dependencies_by_name(UNIT(n), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true);
                 if (r < 0)
                         return r;
@@ -322,7 +318,7 @@ static int busname_open_fd(BusName *n) {
         if (n->starter_fd >= 0)
                 return 0;
 
-        mode = UNIT(n)->manager->running_as == MANAGER_SYSTEM ? "system" : "user";
+        mode = MANAGER_IS_SYSTEM(UNIT(n)->manager) ? "system" : "user";
         n->starter_fd = bus_kernel_open_bus_fd(mode, &path);
         if (n->starter_fd < 0)
                 return log_unit_warning_errno(UNIT(n), n->starter_fd, "Failed to open %s: %m", path ?: "kdbus");
@@ -364,16 +360,15 @@ static int busname_coldplug(Unit *u) {
         if (n->deserialized_state == n->state)
                 return 0;
 
-        if (IN_SET(n->deserialized_state, BUSNAME_MAKING, BUSNAME_SIGTERM, BUSNAME_SIGKILL)) {
-
-                if (n->control_pid <= 0)
-                        return -EBADMSG;
+        if (n->control_pid > 0 &&
+            pid_is_unwaited(n->control_pid) &&
+            IN_SET(n->deserialized_state, BUSNAME_MAKING, BUSNAME_SIGTERM, BUSNAME_SIGKILL)) {
 
                 r = unit_watch_pid(UNIT(n), n->control_pid);
                 if (r < 0)
                         return r;
 
-                r = busname_arm_timer(n);
+                r = busname_arm_timer(n, usec_add(u->state_change_timestamp.monotonic, n->timeout_usec));
                 if (r < 0)
                         return r;
         }
@@ -398,7 +393,7 @@ static int busname_make_starter(BusName *n, pid_t *_pid) {
         pid_t pid;
         int r;
 
-        r = busname_arm_timer(n);
+        r = busname_arm_timer(n, usec_add(now(CLOCK_MONOTONIC), n->timeout_usec));
         if (r < 0)
                 goto fail;
 
@@ -447,7 +442,7 @@ fail:
 static void busname_enter_dead(BusName *n, BusNameResult f) {
         assert(n);
 
-        if (f != BUSNAME_SUCCESS)
+        if (n->result == BUSNAME_SUCCESS)
                 n->result = f;
 
         busname_set_state(n, n->result != BUSNAME_SUCCESS ? BUSNAME_FAILED : BUSNAME_DEAD);
@@ -459,7 +454,7 @@ static void busname_enter_signal(BusName *n, BusNameState state, BusNameResult f
 
         assert(n);
 
-        if (f != BUSNAME_SUCCESS)
+        if (n->result == BUSNAME_SUCCESS)
                 n->result = f;
 
         kill_context_init(&kill_context);
@@ -476,7 +471,7 @@ static void busname_enter_signal(BusName *n, BusNameState state, BusNameResult f
         }
 
         if (r > 0) {
-                r = busname_arm_timer(n);
+                r = busname_arm_timer(n, usec_add(now(CLOCK_MONOTONIC), n->timeout_usec));
                 if (r < 0) {
                         log_unit_warning_errno(UNIT(n), r, "Failed to arm timer: %m");
                         goto fail;
@@ -558,7 +553,7 @@ fail:
 }
 
 static void busname_enter_running(BusName *n) {
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         bool pending = false;
         Unit *other;
         Iterator i;
@@ -597,7 +592,7 @@ static void busname_enter_running(BusName *n) {
                         goto fail;
                 }
 
-                r = manager_add_job(UNIT(n)->manager, JOB_START, UNIT_DEREF(n->service), JOB_REPLACE, true, &error, NULL);
+                r = manager_add_job(UNIT(n)->manager, JOB_START, UNIT_DEREF(n->service), JOB_REPLACE, &error, NULL);
                 if (r < 0)
                         goto fail;
         }
@@ -612,6 +607,7 @@ fail:
 
 static int busname_start(Unit *u) {
         BusName *n = BUSNAME(u);
+        int r;
 
         assert(n);
 
@@ -637,6 +633,16 @@ static int busname_start(Unit *u) {
 
         assert(IN_SET(n->state, BUSNAME_DEAD, BUSNAME_FAILED));
 
+        r = unit_start_limit_test(u);
+        if (r < 0) {
+                busname_enter_dead(n, BUSNAME_FAILURE_START_LIMIT_HIT);
+                return r;
+        }
+
+        r = unit_acquire_invocation_id(u);
+        if (r < 0)
+                return r;
+
         n->result = BUSNAME_SUCCESS;
         busname_enter_making(n);
 
@@ -880,7 +886,7 @@ static void busname_sigchld_event(Unit *u, pid_t pid, int code, int status) {
         log_unit_full(u, f == BUSNAME_SUCCESS ? LOG_DEBUG : LOG_NOTICE, 0,
                       "Control process exited, code=%s status=%i", sigchld_code_to_string(code), status);
 
-        if (f != BUSNAME_SUCCESS)
+        if (n->result == BUSNAME_SUCCESS)
                 n->result = f;
 
         switch (n->state) {
@@ -948,7 +954,6 @@ static void busname_reset_failed(Unit *u) {
 
 static void busname_trigger_notify(Unit *u, Unit *other) {
         BusName *n = BUSNAME(u);
-        Service *s;
 
         assert(n);
         assert(other);
@@ -956,46 +961,56 @@ static void busname_trigger_notify(Unit *u, Unit *other) {
         if (!IN_SET(n->state, BUSNAME_RUNNING, BUSNAME_LISTENING))
                 return;
 
-        if (other->load_state != UNIT_LOADED || other->type != UNIT_SERVICE)
+        if (other->start_limit_hit) {
+                busname_enter_dead(n, BUSNAME_FAILURE_SERVICE_START_LIMIT_HIT);
                 return;
+        }
 
-        s = SERVICE(other);
+        if (other->load_state != UNIT_LOADED || other->type != UNIT_SERVICE)
+                return;
 
-        if (s->state == SERVICE_FAILED && s->result == SERVICE_FAILURE_START_LIMIT)
-                busname_enter_dead(n, BUSNAME_FAILURE_SERVICE_FAILED_PERMANENT);
-        else if (IN_SET(s->state,
-                        SERVICE_DEAD, SERVICE_FAILED,
-                        SERVICE_STOP, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL,
-                        SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL,
-                        SERVICE_AUTO_RESTART))
+        if (IN_SET(SERVICE(other)->state,
+                   SERVICE_DEAD, SERVICE_FAILED,
+                   SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL,
+                   SERVICE_AUTO_RESTART))
                 busname_enter_listening(n);
+
+        if (SERVICE(other)->state == SERVICE_RUNNING)
+                busname_set_state(n, BUSNAME_RUNNING);
 }
 
 static int busname_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
         return unit_kill_common(u, who, signo, -1, BUSNAME(u)->control_pid, error);
 }
 
-static int busname_get_timeout(Unit *u, uint64_t *timeout) {
+static int busname_get_timeout(Unit *u, usec_t *timeout) {
         BusName *n = BUSNAME(u);
+        usec_t t;
         int r;
 
         if (!n->timer_event_source)
                 return 0;
 
-        r = sd_event_source_get_time(n->timer_event_source, timeout);
+        r = sd_event_source_get_time(n->timer_event_source, &t);
         if (r < 0)
                 return r;
+        if (t == USEC_INFINITY)
+                return 0;
 
+        *timeout = t;
         return 1;
 }
 
 static bool busname_supported(void) {
-        static int supported = -1;
+        return false;
+}
 
-        if (supported < 0)
-                supported = is_kdbus_available();
+static int busname_control_pid(Unit *u) {
+        BusName *n = BUSNAME(u);
 
-        return supported;
+        assert(n);
+
+        return n->control_pid;
 }
 
 static const char* const busname_result_table[_BUSNAME_RESULT_MAX] = {
@@ -1005,7 +1020,8 @@ static const char* const busname_result_table[_BUSNAME_RESULT_MAX] = {
         [BUSNAME_FAILURE_EXIT_CODE] = "exit-code",
         [BUSNAME_FAILURE_SIGNAL] = "signal",
         [BUSNAME_FAILURE_CORE_DUMP] = "core-dump",
-        [BUSNAME_FAILURE_SERVICE_FAILED_PERMANENT] = "service-failed-permanent",
+        [BUSNAME_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
+        [BUSNAME_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit",
 };
 
 DEFINE_STRING_TABLE_LOOKUP(busname_result, BusNameResult);
@@ -1019,9 +1035,6 @@ const UnitVTable busname_vtable = {
                 "Install\0",
         .private_section = "BusName",
 
-        .no_alias = true,
-        .no_instances = true,
-
         .init = busname_init,
         .done = busname_done,
         .load = busname_load,
@@ -1051,6 +1064,8 @@ const UnitVTable busname_vtable = {
 
         .supported = busname_supported,
 
+        .control_pid = busname_control_pid,
+
         .bus_vtable = bus_busname_vtable,
 
         .status_message_formats = {