chiark / gitweb /
service: fix auto-restart handling in service_start()
[elogind.git] / src / core / service.c
index 2bd29ff7e6333254adbf3c54f2a0143a67ace7c7..5d82e9b545172516147b59956ac8e386bfd64852 100644 (file)
@@ -2232,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
@@ -2434,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);
@@ -2458,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 */
@@ -2471,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;
         }