From ad1821f69ee17aa67a3a0ba908c01dbcbd69d90b Mon Sep 17 00:00:00 2001 From: Davin McCall Date: Tue, 7 Jun 2016 08:30:00 +0100 Subject: [PATCH] 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. --- src/service.cc | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) 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. -- 2.25.1