Handle fork+exec failure in a separate virtual method.
authorDavin McCall <davmac@davmac.org>
Sun, 31 Dec 2017 16:29:31 +0000 (16:29 +0000)
committerDavin McCall <davmac@davmac.org>
Sun, 31 Dec 2017 16:29:31 +0000 (16:29 +0000)
This cleans up the code and removes a lot of conditional handling for
the different service types.

src/service.cc
src/service.h

index a46a59c2cb804f4eba7a1a387af2fec4f78c4a34..7f030885e6bd80305153eb2a2648876853d7973d 100644 (file)
@@ -163,6 +163,14 @@ void service_record::emergency_stop() noexcept
     stopped();
 }
 
+void base_process_service::do_smooth_recovery() noexcept
+{
+    if (! restart_ps_process()) {
+        emergency_stop();
+        services->process_queues();
+    }
+}
+
 void process_service::handle_exit_status(int exit_status) noexcept
 {
     bool did_exit = WIFEXITED(exit_status);
@@ -204,11 +212,15 @@ void process_service::handle_exit_status(int exit_status) noexcept
     services->process_queues();
 }
 
-void base_process_service::do_smooth_recovery() noexcept
+void process_service::exec_failed(int errcode) noexcept
 {
-    if (! restart_ps_process()) {
+    log(loglevel_t::ERROR, service_name, ": execution failed: ", strerror(errcode));
+    if (service_state == service_state_t::STARTING) {
+        failed_to_start();
+    }
+    else {
+        // Process service in smooth recovery:
         emergency_stop();
-        services->process_queues();
     }
 }
 
@@ -309,6 +321,13 @@ void bgproc_service::handle_exit_status(int exit_status) noexcept
     services->process_queues();
 }
 
+void bgproc_service::exec_failed(int errcode) noexcept
+{
+    log(loglevel_t::ERROR, service_name, ": execution failed: ", strerror(errcode));
+    // Only time we execute is for startup:
+    failed_to_start();
+}
+
 void scripted_service::handle_exit_status(int exit_status) noexcept
 {
     bool did_exit = WIFEXITED(exit_status);
@@ -354,6 +373,19 @@ void scripted_service::handle_exit_status(int exit_status) noexcept
     }
 }
 
+void scripted_service::exec_failed(int errcode) noexcept
+{
+    log(loglevel_t::ERROR, service_name, ": execution failed: ", strerror(errcode));
+    if (service_state == service_state_t::STARTING) {
+        failed_to_start();
+    }
+    else if (service_state == service_state_t::STOPPING) {
+        // We've logged the failure, but it's probably better not to leave the service in
+        // STOPPING state:
+        stopped();
+    }
+}
+
 rearm exec_status_pipe_watcher::fd_event(eventloop_t &loop, int fd, int flags) noexcept
 {
     base_process_service *sr = service;
@@ -375,28 +407,7 @@ rearm exec_status_pipe_watcher::fd_event(eventloop_t &loop, int fd, int flags) n
             }
         }
         sr->pid = -1;
-        log(loglevel_t::ERROR, sr->service_name, ": execution failed: ", strerror(exec_status));
-        if (sr->service_state == service_state_t::STARTING) {
-            sr->failed_to_start();
-        }
-        else if (sr->service_state == service_state_t::STOPPING) {
-            // Must be a scripted service, or a regular process service that happened to be in smooth
-            // recovery when the stop was issued.
-            if (sr->record_type == service_type::PROCESS) {
-                if (sr->stop_check_dependents()) {
-                    sr->stopped();
-                }
-            }
-            else {
-                // We've logged the failure, but it's probably better not to leave the service in
-                // STOPPING state:
-                sr->stopped();
-            }
-        }
-        else if (sr->service_state == service_state_t::STARTED) {
-            // Process service in smooth recovery:
-            sr->emergency_stop();
-        }
+        sr->exec_failed(exec_status);
     }
     else {
         // exec() succeeded.
index 7d78c4a2914e798d7e480ef95ef7e6d22aba49f1..b9f6c6a0ac0e957a45ed5fd18eb88da46af85710 100644 (file)
@@ -666,6 +666,7 @@ class base_process_service : public service_record
     // Called when the process exits. The exit_status is the status value yielded by
     // the "wait" system call.
     virtual void handle_exit_status(int exit_status) noexcept = 0;
+    virtual void exec_failed(int errcode) noexcept = 0;
 
     virtual bool can_interrupt_start() noexcept override
     {
@@ -714,6 +715,7 @@ class base_process_service : public service_record
 class process_service : public base_process_service
 {
     virtual void handle_exit_status(int exit_status) noexcept override;
+    virtual void exec_failed(int errcode) noexcept override;
     virtual void all_deps_stopped() noexcept override;
 
     public:
@@ -733,6 +735,7 @@ class process_service : public base_process_service
 class bgproc_service : public base_process_service
 {
     virtual void handle_exit_status(int exit_status) noexcept override;
+    virtual void exec_failed(int errcode) noexcept override;
 
     enum class pid_result_t {
         OK,
@@ -759,8 +762,9 @@ class bgproc_service : public base_process_service
 
 class scripted_service : public base_process_service
 {
-    virtual void all_deps_stopped() noexcept override;
     virtual void handle_exit_status(int exit_status) noexcept override;
+    virtual void exec_failed(int errcode) noexcept override;
+    virtual void all_deps_stopped() noexcept override;
 
     public:
     scripted_service(service_set *sset, string name, string &&command,