From: Davin McCall Date: Tue, 7 Jun 2016 07:30:00 +0000 (+0100) Subject: Avoid hanging if a BGPROCESS is not a child of dinit, by probing X-Git-Tag: v0.02~6 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=ad1821f69ee17aa67a3a0ba908c01dbcbd69d90b;p=oweals%2Fdinit.git Avoid hanging if a BGPROCESS is not a child of dinit, by probing status with waitpid() and assuming the process is stopped if it is not a child. --- diff --git a/src/service.cc b/src/service.cc index 5090f75..47ba9de 100644 --- a/src/service.cc +++ b/src/service.cc @@ -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.