chiark / gitweb /
manager: configurable StartLimit default values
[elogind.git] / src / core / service.c
index 4070fd741bf0f8dfa926fc0b4de5571b7aae02c2..3da32a162172166ec3d64aac0985e81d734d283e 100644 (file)
@@ -124,9 +124,9 @@ static void service_init(Unit *u) {
         assert(u);
         assert(u->load_state == UNIT_STUB);
 
-        s->timeout_start_usec = DEFAULT_TIMEOUT_USEC;
-        s->timeout_stop_usec = DEFAULT_TIMEOUT_USEC;
-        s->restart_usec = DEFAULT_RESTART_USEC;
+        s->timeout_start_usec = u->manager->default_timeout_start_usec;
+        s->timeout_stop_usec = u->manager->default_timeout_stop_usec;
+        s->restart_usec = u->manager->default_restart_usec;
         s->type = _SERVICE_TYPE_INVALID;
 
         watch_init(&s->watchdog_watch);
@@ -143,7 +143,9 @@ static void service_init(Unit *u) {
         kill_context_init(&s->kill_context);
         cgroup_context_init(&s->cgroup_context);
 
-        RATELIMIT_INIT(s->start_limit, 10*USEC_PER_SEC, 5);
+        RATELIMIT_INIT(s->start_limit,
+                       u->manager->default_start_limit_interval,
+                       u->manager->default_start_limit_burst);
 
         s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID;
 }
@@ -191,7 +193,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 +213,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;
 }
 
@@ -1052,48 +1058,6 @@ static int service_load_sysv(Service *s) {
 }
 #endif
 
-static int fsck_fix_order(Service *s) {
-        Unit *other;
-        int r;
-
-        assert(s);
-
-        if (s->fsck_passno <= 0)
-                return 0;
-
-        /* For each pair of services where both have an fsck priority
-         * we order things based on it. */
-
-        LIST_FOREACH(units_by_type, other, UNIT(s)->manager->units_by_type[UNIT_SERVICE]) {
-                Service *t;
-                UnitDependency d;
-
-                t = SERVICE(other);
-
-                if (s == t)
-                        continue;
-
-                if (UNIT(t)->load_state != UNIT_LOADED)
-                        continue;
-
-                if (t->fsck_passno <= 0)
-                        continue;
-
-                if (t->fsck_passno < s->fsck_passno)
-                        d = UNIT_AFTER;
-                else if (t->fsck_passno > s->fsck_passno)
-                        d = UNIT_BEFORE;
-                else
-                        continue;
-
-                r = unit_add_dependency(UNIT(s), d, UNIT(t), true);
-                if (r < 0)
-                        return r;
-        }
-
-        return 0;
-}
-
 static int service_verify(Service *s) {
         assert(s);
 
@@ -1250,10 +1214,6 @@ static int service_load(Unit *u) {
                         return r;
 #endif
 
-                r = fsck_fix_order(s);
-                if (r < 0)
-                        return r;
-
                 if (s->bus_name)
                         if ((r = unit_watch_bus_name(u, s->bus_name)) < 0)
                                 return r;
@@ -1377,11 +1337,6 @@ static void service_dump(Unit *u, FILE *f, const char *prefix) {
                         prefix, s->sysv_runlevels);
 #endif
 
-        if (s->fsck_passno > 0)
-                fprintf(f,
-                        "%sFsckPassNo: %i\n",
-                        prefix, s->fsck_passno);
-
         if (s->status_text)
                 fprintf(f, "%sStatus Text: %s\n",
                         prefix, s->status_text);
@@ -1489,24 +1444,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 +1495,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 +1720,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 +1775,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 +1859,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 ||
@@ -1957,6 +1880,12 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart)
         /* we want fresh tmpdirs in case service is started again immediately */
         exec_context_tmp_dirs_done(&s->exec_context);
 
+        /* Try to delete the pid file. At this point it will be
+         * out-of-date, and some software might be confused by it, so
+         * let's remove it. */
+        if (s->pid_file)
+                unlink_noerrno(s->pid_file);
+
         return;
 
 fail:
@@ -2673,6 +2602,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;
 }
 
@@ -2722,8 +2654,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;
 
@@ -2807,6 +2741,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);
 
@@ -3415,6 +3357,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);
                 }
         }
 
@@ -3711,8 +3654,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) {
@@ -3785,6 +3730,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"
 };