From: Davin McCall Date: Sun, 12 Jun 2016 09:00:49 +0000 (+0100) Subject: Code consistency and documentation update X-Git-Tag: v0.03~31 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=ae8031f93e0804c912d69d909d7c3383d609a611;p=oweals%2Fdinit.git Code consistency and documentation update --- diff --git a/src/service.cc b/src/service.cc index b3bbf16..5827e23 100644 --- a/src/service.cc +++ b/src/service.cc @@ -69,17 +69,20 @@ void ServiceRecord::stopped() noexcept releaseConsole(); } - logServiceStopped(service_name); service_state = ServiceState::STOPPED; force_stop = false; + logServiceStopped(service_name); notifyListeners(ServiceEvent::STOPPED); + bool will_restart = (desired_state == ServiceState::STARTED) && service_set->get_auto_restart(); for (auto dependency : depends_on) { - dependency->dependentStopped(); + if (! will_restart || ! dependency->can_interrupt_stop()) { + dependency->dependentStopped(); + } } - if (desired_state == ServiceState::STARTED && service_set->get_auto_restart()) { + if (will_restart) { // Desired state is "started". do_start(); } @@ -150,7 +153,7 @@ void ServiceRecord::handle_exit_status() noexcept if (need_stop) { // Failed startup: no auto-restart. desired_state = ServiceState::STOPPED; - do_stop(); + forceStop(); } return; @@ -305,15 +308,16 @@ void ServiceRecord::release_dependencies() noexcept void ServiceRecord::start(bool activate) noexcept { - if (activate) { - if (!start_explicit) require(); + if (activate && ! start_explicit) { + require(); start_explicit = true; } if (desired_state == ServiceState::STARTED && service_state != ServiceState::STOPPED) return; if (required_by == 0) { - service_set->service_active(this); + // It really doesn't make any sense to start if there is no dependent or explicit activation. + return; } desired_state = ServiceState::STARTED; @@ -753,7 +757,7 @@ void ServiceRecord::stop(bool bring_down) noexcept release(); } - if (bring_down) { + if (bring_down && desired_state != ServiceState::STOPPED) { desired_state = ServiceState::STOPPED; do_stop(); } @@ -829,7 +833,7 @@ bool ServiceRecord::stopDependents() noexcept return all_deps_stopped; } -// All dependents have stopped; we can stop now, too. +// All dependents have stopped; we can stop now, too. Only called when STOPPING. void ServiceRecord::allDepsStopped() { waiting_for_deps = false; @@ -850,7 +854,7 @@ void ServiceRecord::allDepsStopped() int status; pid_t r = waitpid(pid, &status, WNOHANG); if (r == -1 && errno == ECHILD) { - // We can't track this child + // We can't track this child (or it's terminated already) stopped(); } else if (r == pid) { @@ -884,7 +888,7 @@ void ServiceRecord::unpin() noexcept if (pinned_started) { pinned_started = false; if (desired_state == ServiceState::STOPPED) { - stop(); + do_stop(); } } if (pinned_stopped) { diff --git a/src/service.h b/src/service.h index 2cd5a00..4775fcf 100644 --- a/src/service.h +++ b/src/service.h @@ -48,6 +48,26 @@ * each dependent service which is not STOPPED (including depdendents with a soft dependency). * When required_by transitions to 0, the service is stopped (unless it is pinned). When * require_by transitions from 0, the service is started (unless pinned). + * + * So, in general, the dependent-count determines the desired state (STARTED if the count + * is greater than 0, otherwise STOPPED). However, a service can be issued a stop-and-take + * down order (via `stop(true)'); this will first stop dependent services, which may restart + * and cancel the stop of the former service. Finally, a service can be force-stopped, which + * means that its stop process cannot be cancelled (though it may still be put in a desired + * state of STARTED, meaning it will start immediately upon stopping). + * + * Pinning + * ------- + * A service may be "pinned" in either STARTED or STOPPED states (or even both). Once it + * reaches a pinned state, a service will not leave that state, though its desired state + * may still be set. (Note that pinning prevents, but never causes, state transition). + * + * The priority of the different state deciders is: + * - pins + * - force stop flag + * - desired state (which is manipulated by require/release operations) + * + * So a forced stop cannot occur until the service is not pinned started, for instance. */ struct OnstartFlags { @@ -294,8 +314,11 @@ class ServiceRecord int revents) noexcept; void handle_exit_status() noexcept; - + + // Called on transition of desired state from stopped to started (or unpinned stop) void do_start() noexcept; + + // Called on transition of desired state from started to stopped (or unpinned start) void do_stop() noexcept; // A dependency has reached STARTED state