Refactoring, and one fix: stopping an already-stopped service can be
authorDavin McCall <davmac@davmac.org>
Sat, 9 Jan 2016 19:59:36 +0000 (19:59 +0000)
committerDavin McCall <davmac@davmac.org>
Sat, 9 Jan 2016 19:59:36 +0000 (19:59 +0000)
used to remove its explicitly-started state, and in that case needs
to notify dependencies of complete shutdown.

src/service.cc
src/service.h

index 105c08bc60111b44a670be2ed7e3fa34da4b6d36..0e90b68e811e7268522bdb3954516249c7943b8a 100644 (file)
@@ -56,6 +56,21 @@ void ServiceSet::stopService(const std::string & name) noexcept
     }
 }
 
+void ServiceRecord::notify_dependencies_stopped() noexcept
+{
+    if (desired_state == ServiceState::STOPPED) {
+        // Stop any dependencies whose desired state is STOPPED:
+        for (auto i = depends_on.begin(); i != depends_on.end(); i++) {
+            (*i)->dependentStopped();
+        }
+        for (auto i = soft_deps.begin(); i != soft_deps.end(); i++) {
+            i->getTo()->dependentStopped();
+        }
+        
+        service_set->service_inactive(this);
+    }
+}
+
 // Called when a service has actually stopped.
 void ServiceRecord::stopped() noexcept
 {
@@ -80,15 +95,7 @@ void ServiceRecord::stopped() noexcept
             socket_fd = -1;
         }
         
-        service_set->service_inactive(this);
-        
-        // Stop any dependencies whose desired state is STOPPED:
-        for (auto i = depends_on.begin(); i != depends_on.end(); i++) {
-            (*i)->dependentStopped();
-        }
-        for (auto i = soft_deps.begin(); i != soft_deps.end(); i++) {
-            i->getTo()->dependentStopped();
-        }
+        notify_dependencies_stopped();
     }
 }
 
@@ -522,17 +529,9 @@ void ServiceRecord::failed_to_start(bool depfailed) noexcept
     
     logServiceFailed(service_name);
     service_state = ServiceState::STOPPED;
-    desired_state = ServiceState::STOPPED;
-    service_set->service_inactive(this);
     notifyListeners(ServiceEvent::FAILEDSTART);
     
-    // Stop any dependencies whose desired state is STOPPED:
-    for (auto i = depends_on.begin(); i != depends_on.end(); i++) {
-        (*i)->dependentStopped();
-    }
-    for (auto i = soft_deps.begin(); i != soft_deps.end(); i++) {
-        i->getTo()->dependentStopped();
-    }
+    notify_dependencies_stopped();
 
     // Cancel start of dependents:
     for (sr_iter i = dependents.begin(); i != dependents.end(); i++) {
@@ -716,6 +715,11 @@ void ServiceRecord::stop() noexcept
     }
     
     desired_state = ServiceState::STOPPED;
+
+    if (service_state == ServiceState::STOPPED) {
+        notify_dependencies_stopped();
+        return;
+    }
     
     do_stop();
 }
index 3e5211b786f3761ea09cb572f9de259325b329a8..ffd28898d70e8440391dd58af4605844e4882c99 100644 (file)
@@ -282,6 +282,10 @@ class ServiceRecord
         return waiting_for_deps && ! force_stop;
     }
 
+    // Notify dependencies that we no longer need them,
+    // (if this is actually the case).
+    void notify_dependencies_stopped() noexcept;
+
     // A dependent has reached STOPPED state
     void dependentStopped() noexcept;