chiark / gitweb /
service: fix auto-restart handling in service_start()
[elogind.git] / src / core / service.c
index 28049a33c70ee61d576dd056b8a760f47db5cac6..5d82e9b545172516147b59956ac8e386bfd64852 100644 (file)
@@ -110,6 +110,7 @@ static const UnitActiveState state_translation_table[_SERVICE_STATE_MAX] = {
 
 static void service_init(Unit *u) {
         Service *s = SERVICE(u);
+        int i;
 
         assert(u);
         assert(u->load_state == UNIT_STUB);
@@ -129,6 +130,9 @@ static void service_init(Unit *u) {
         s->guess_main_pid = true;
 
         exec_context_init(&s->exec_context);
+        for (i = 0; i < RLIMIT_NLIMITS; i++)
+                if (UNIT(s)->manager->rlimit[i])
+                        s->exec_context.rlimit[i] = newdup(struct rlimit, UNIT(s)->manager->rlimit[i], 1);
 
         RATELIMIT_INIT(s->start_limit, 10*USEC_PER_SEC, 5);
 
@@ -2228,6 +2232,8 @@ static void service_enter_restart(Service *s) {
 
                 if ((r = unit_watch_timer(UNIT(s), s->restart_usec, &s->timer_watch)) < 0)
                         goto fail;
+
+                return;
         }
 
         /* Any units that are bound to this service must also be
@@ -2430,7 +2436,16 @@ static int service_start(Unit *u) {
             s->state == SERVICE_START_POST)
                 return 0;
 
-        assert(s->state == SERVICE_DEAD || s->state == SERVICE_FAILED || s->state == SERVICE_AUTO_RESTART);
+        /* A service that will be restarted must be stopped first to
+         * trigger BindTo and/or OnFailure dependencies. If a user
+         * does not want to wait for the holdoff time to elapse, the
+         * service should be manually restarted, not started. */
+        if (s->state == SERVICE_AUTO_RESTART) {
+                log_warning("%s automatic restart is pending, must be stopped before issuing start request.", UNIT(s)->id);
+                return -ECANCELED;
+        }
+
+        assert(s->state == SERVICE_DEAD || s->state == SERVICE_FAILED);
 
         /* Make sure we don't enter a busy loop of some kind. */
         r = service_start_limit_test(s);
@@ -2454,8 +2469,7 @@ static int service_stop(Unit *u) {
 
         assert(s);
 
-        /* This is a user request, so don't do restarts on this
-         * shutdown. */
+        /* Don't create restart jobs from here. */
         s->forbid_restart = true;
 
         /* Already on it */
@@ -2467,9 +2481,9 @@ static int service_stop(Unit *u) {
             s->state == SERVICE_FINAL_SIGKILL)
                 return 0;
 
-        /* Don't allow a restart */
+        /* A restart will be scheduled or is in progress. */
         if (s->state == SERVICE_AUTO_RESTART) {
-                service_set_state(s, SERVICE_DEAD);
+                service_enter_dead(s, SERVICE_SUCCESS, false);
                 return 0;
         }