Break holds from soft dependents if a service is manually stopped.
authorDavin McCall <davmac@davmac.org>
Wed, 29 May 2019 08:56:19 +0000 (18:56 +1000)
committerDavin McCall <davmac@davmac.org>
Wed, 29 May 2019 10:17:29 +0000 (20:17 +1000)
If all dependents are soft (waits-for or soft) then break their holds on
a service that is manually stopped. This prevents the service from
immediately re-starting, which would be unexpected behaviour.

src/service.cc

index bf5d68252a620e57444c50c9c1ebda0433c47b04..34dde07fed3f556990b26882db7120771a8e0d99 100644 (file)
@@ -457,6 +457,26 @@ void service_record::stop(bool bring_down) noexcept
         release();
     }
 
+    // If it's a manual bring-down, we'll also break holds from waits-for dependencies, to avoid
+    // bouncing back up again -- but only if all holds are from waits-for dependencies.
+    if (bring_down) {
+        if (std::all_of(dependents.begin(), dependents.end(), [](service_dep * x) {
+            return x->dep_type == dependency_type::WAITS_FOR || x->dep_type == dependency_type::SOFT; }))
+        {
+            for (auto dept : dependents) {
+                if (dept->waiting_on) {
+                    dept->waiting_on = false;
+                    dept->get_from()->dependency_started();
+                }
+                if (dept->holding_acq) {
+                    dept->holding_acq = false;
+                    // release without issuing stop, since we issue stop if necessary below
+                    release(false);
+                }
+            }
+        }
+    }
+
     if (bring_down && service_state != service_state_t::STOPPED
                && service_state != service_state_t::STOPPING) {
        stop_reason = stopped_reason_t::NORMAL;