Avoid hanging if a BGPROCESS is not a child of dinit, by probing
authorDavin McCall <davmac@davmac.org>
Tue, 7 Jun 2016 07:30:00 +0000 (08:30 +0100)
committerDavin McCall <davmac@davmac.org>
Tue, 7 Jun 2016 07:30:00 +0000 (08:30 +0100)
status with waitpid() and assuming the process is stopped if it
is not a child.

src/service.cc

index 5090f75399904bb88679e6293e732f9ce28601a4..47ba9de25848e436d309278b5597ca9a23887a1b 100644 (file)
@@ -829,7 +829,7 @@ bool ServiceRecord::stopDependents() noexcept
     return all_deps_stopped;
 }
 
-// Dependency stopped or is stopping; we must stop too.
+// All dependents have stopped; we can stop now, too.
 void ServiceRecord::allDepsStopped()
 {
     waiting_for_deps = false;
@@ -842,7 +842,22 @@ void ServiceRecord::allDepsStopped()
             if (term_signal != -1) {
                 kill(pid, term_signal);
             }
-            // Now we wait; the rest is done in process_child_callback
+            
+            // In most cases, the rest is done in process_child_callback.
+            // If we are a BGPROCESS and the process is not our immediate child, however, that
+            // won't work - check for this now:
+            if (service_type == ServiceType::BGPROCESS) {
+                int status;
+                pid_t r = waitpid(pid, &status, WNOHANG);
+                if (r == -1 && errno == ECHILD) {
+                    // We can't track this child
+                    stopped();
+                }
+                else if (r == pid) {
+                    // TODO, examine status and log anything unusual.
+                    stopped();
+                }
+            }
         }
         else {
             // The process is already dead.