chiark / gitweb /
systemd: serialize/deserialize forbid_restart value
[elogind.git] / src / core / service.c
index 34dde7963e6fdd6d53b375ce37e1953f8004be82..98b1599a32f86a61e67e32e2ddb29ba79b01d2ec 100644 (file)
@@ -191,7 +191,13 @@ static int service_set_main_pid(Service *s, pid_t pid) {
         if (pid == getpid())
                 return -EINVAL;
 
-        service_unwatch_main_pid(s);
+        if (s->main_pid == pid && s->main_pid_known)
+                return 0;
+
+        if (s->main_pid != pid) {
+                service_unwatch_main_pid(s);
+                exec_status_start(&s->main_exec_status, pid);
+        }
 
         s->main_pid = pid;
         s->main_pid_known = true;
@@ -205,8 +211,6 @@ static int service_set_main_pid(Service *s, pid_t pid) {
         } else
                 s->main_pid_alien = false;
 
-        exec_status_start(&s->main_exec_status, pid);
-
         return 0;
 }
 
@@ -1489,24 +1493,6 @@ static int service_search_main_pid(Service *s) {
         return 0;
 }
 
-static void service_notify_sockets_dead(Service *s, bool failed_permanent) {
-        Iterator i;
-        Unit *u;
-
-        assert(s);
-
-        /* Notifies all our sockets when we die */
-
-        if (s->socket_fd >= 0)
-                return;
-
-        SET_FOREACH(u, UNIT(s)->dependencies[UNIT_TRIGGERED_BY], i)
-                if (u->type == UNIT_SOCKET)
-                        socket_notify_service_dead(SOCKET(u), failed_permanent);
-
-        return;
-}
-
 static void service_set_state(Service *s, ServiceState state) {
         ServiceState old_state;
         const UnitActiveState *table;
@@ -1558,19 +1544,6 @@ static void service_set_state(Service *s, ServiceState state) {
                 s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID;
         }
 
-        if (state == SERVICE_FAILED)
-                service_notify_sockets_dead(s, s->result == SERVICE_FAILURE_START_LIMIT);
-
-        if (state == SERVICE_DEAD ||
-            state == SERVICE_STOP ||
-            state == SERVICE_STOP_SIGTERM ||
-            state == SERVICE_STOP_SIGKILL ||
-            state == SERVICE_STOP_POST ||
-            state == SERVICE_FINAL_SIGTERM ||
-            state == SERVICE_FINAL_SIGKILL ||
-            state == SERVICE_AUTO_RESTART)
-                service_notify_sockets_dead(s, false);
-
         if (state != SERVICE_START_PRE &&
             state != SERVICE_START &&
             state != SERVICE_START_POST &&
@@ -1796,11 +1769,9 @@ static int service_spawn(
         } else
                 unit_unwatch_timer(UNIT(s), &s->timer_watch);
 
-        argv = unit_full_printf_strv(UNIT(s), c->argv);
-        if (!argv) {
-                r = -ENOMEM;
+        r = unit_full_printf_strv(UNIT(s), c->argv, &argv);
+        if (r < 0)
                 goto fail;
-        }
 
         our_env = new0(char*, 5);
         if (!our_env) {
@@ -1853,7 +1824,7 @@ static int service_spawn(
                        apply_chroot,
                        apply_tty_stdin,
                        UNIT(s)->manager->confirm_spawn,
-                       UNIT(s)->cgroup_mask,
+                       UNIT(s)->manager->cgroup_supported,
                        path,
                        UNIT(s)->id,
                        s->type == SERVICE_IDLE ? UNIT(s)->manager->idle_pipe : NULL,
@@ -1937,6 +1908,7 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart)
             (s->restart == SERVICE_RESTART_ALWAYS ||
              (s->restart == SERVICE_RESTART_ON_SUCCESS && s->result == SERVICE_SUCCESS) ||
              (s->restart == SERVICE_RESTART_ON_FAILURE && s->result != SERVICE_SUCCESS) ||
+             (s->restart == SERVICE_RESTART_ON_WATCHDOG && s->result == SERVICE_FAILURE_WATCHDOG) ||
              (s->restart == SERVICE_RESTART_ON_ABORT && (s->result == SERVICE_FAILURE_SIGNAL ||
                                                          s->result == SERVICE_FAILURE_CORE_DUMP))) &&
             (s->result != SERVICE_FAILURE_EXIT_CODE ||
@@ -2679,6 +2651,9 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
         if (s->exec_context.var_tmp_dir)
                 unit_serialize_item(u, f, "var-tmp-dir", s->exec_context.var_tmp_dir);
 
+        if (s->forbid_restart)
+                unit_serialize_item(u, f, "forbid_restart", yes_no(s->forbid_restart));
+
         return 0;
 }
 
@@ -2728,8 +2703,10 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value,
 
                 if (parse_pid(value, &pid) < 0)
                         log_debug_unit(u->id, "Failed to parse main-pid value %s", value);
-                else
-                        service_set_main_pid(s, (pid_t) pid);
+                else {
+                        service_set_main_pid(s, pid);
+                        unit_watch_pid(UNIT(s), pid);
+                }
         } else if (streq(key, "main-pid-known")) {
                 int b;
 
@@ -2813,6 +2790,14 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value,
                         return log_oom();
 
                 s->exec_context.var_tmp_dir = t;
+        } else if (streq(key, "forbid_restart")) {
+                int b;
+
+                b = parse_boolean(value);
+                if (b < 0)
+                        log_debug_unit(u->id, "Failed to parse forbid_restart value %s", value);
+                else
+                        s->forbid_restart = b;
         } else
                 log_debug_unit(u->id, "Unknown serialization key '%s'", key);
 
@@ -3421,6 +3406,7 @@ static void service_notify_message(Unit *u, pid_t pid, char **tags) {
                         log_debug_unit(u->id,
                                        "%s: got %s", u->id, e);
                         service_set_main_pid(s, pid);
+                        unit_watch_pid(UNIT(s), pid);
                 }
         }
 
@@ -3717,8 +3703,10 @@ static void service_bus_query_pid_done(
             (s->state == SERVICE_START ||
              s->state == SERVICE_START_POST ||
              s->state == SERVICE_RUNNING ||
-             s->state == SERVICE_RELOAD))
+             s->state == SERVICE_RELOAD)){
                 service_set_main_pid(s, pid);
+                unit_watch_pid(UNIT(s), pid);
+        }
 }
 
 int service_set_socket_fd(Service *s, int fd, Socket *sock) {
@@ -3791,6 +3779,7 @@ static const char* const service_restart_table[_SERVICE_RESTART_MAX] = {
         [SERVICE_RESTART_NO] = "no",
         [SERVICE_RESTART_ON_SUCCESS] = "on-success",
         [SERVICE_RESTART_ON_FAILURE] = "on-failure",
+        [SERVICE_RESTART_ON_WATCHDOG] = "on-watchdog",
         [SERVICE_RESTART_ON_ABORT] = "on-abort",
         [SERVICE_RESTART_ALWAYS] = "always"
 };