Browse Source

Propagate failure to dependent if restart threshold exceeded

If a service is restarting too quickly, it stops i.e. further restart
should be inhibited, however as the failure wasn't propagated to
dependents a restarting dependent could cause the service to restart
anyway.

Fix that.

Addresses #249
Davin McCall 6 months ago
parent
commit
822cb0071f
3 changed files with 15 additions and 1 deletions
  1. 1 0
      src/includes/proc-service.h
  2. 6 0
      src/includes/service.h
  3. 8 1
      src/service.cc

+ 1 - 0
src/includes/proc-service.h

@@ -629,6 +629,7 @@ class process_service : public base_process_service
                 // Within the restart limiting interval; check number of restarts
                 if (restart_interval_count >= max_restart_interval_count) {
                     log(loglevel_t::ERROR, "Service ", get_name(), " restarting too quickly; stopping.");
+                    set_target_state(service_state_t::STOPPED);
                     return false;
                 }
                 ++restart_interval_count;

+ 6 - 0
src/includes/service.h

@@ -419,6 +419,12 @@ class service_record
         service_state = new_state;
     }
 
+    // Set the target state
+    void set_target_state(service_state_t new_target_state) noexcept
+    {
+        desired_state = new_target_state;
+    }
+
     // Virtual functions, to be implemented by service implementations:
 
     // Do any post-dependency startup; return false on failure. Should return true if service

+ 8 - 1
src/service.cc

@@ -748,7 +748,14 @@ bool service_record::stop_dependents(bool for_restart, bool restart_deps) noexce
 
             if (force_stop) {
                 // If this service is to be forcefully stopped, dependents must also be.
-                dep_from->forced_stop();
+                if (desired_state == service_state_t::STOPPED) {
+                    // If our target state was forced to STOPPED, this is a failure
+                    dep_from->stop_reason = stopped_reason_t::DEPFAILED;
+                    dep_from->unrecoverable_stop();
+                }
+                else {
+                    dep_from->forced_stop();
+                }
             }
 
             if (dep_from->get_state() != service_state_t::STOPPED) {