From 0a5588cd329ca97b3e712a2d47a373d8a9174276 Mon Sep 17 00:00:00 2001 From: Davin McCall Date: Sat, 9 Jan 2016 19:59:36 +0000 Subject: [PATCH] Refactoring, and one fix: stopping an already-stopped service can be used to remove its explicitly-started state, and in that case needs to notify dependencies of complete shutdown. --- src/service.cc | 40 ++++++++++++++++++++++------------------ src/service.h | 4 ++++ 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/service.cc b/src/service.cc index 105c08b..0e90b68 100644 --- a/src/service.cc +++ b/src/service.cc @@ -56,6 +56,21 @@ void ServiceSet::stopService(const std::string & name) noexcept } } +void ServiceRecord::notify_dependencies_stopped() noexcept +{ + if (desired_state == ServiceState::STOPPED) { + // Stop any dependencies whose desired state is STOPPED: + for (auto i = depends_on.begin(); i != depends_on.end(); i++) { + (*i)->dependentStopped(); + } + for (auto i = soft_deps.begin(); i != soft_deps.end(); i++) { + i->getTo()->dependentStopped(); + } + + service_set->service_inactive(this); + } +} + // Called when a service has actually stopped. void ServiceRecord::stopped() noexcept { @@ -80,15 +95,7 @@ void ServiceRecord::stopped() noexcept socket_fd = -1; } - service_set->service_inactive(this); - - // Stop any dependencies whose desired state is STOPPED: - for (auto i = depends_on.begin(); i != depends_on.end(); i++) { - (*i)->dependentStopped(); - } - for (auto i = soft_deps.begin(); i != soft_deps.end(); i++) { - i->getTo()->dependentStopped(); - } + notify_dependencies_stopped(); } } @@ -522,17 +529,9 @@ void ServiceRecord::failed_to_start(bool depfailed) noexcept logServiceFailed(service_name); service_state = ServiceState::STOPPED; - desired_state = ServiceState::STOPPED; - service_set->service_inactive(this); notifyListeners(ServiceEvent::FAILEDSTART); - // Stop any dependencies whose desired state is STOPPED: - for (auto i = depends_on.begin(); i != depends_on.end(); i++) { - (*i)->dependentStopped(); - } - for (auto i = soft_deps.begin(); i != soft_deps.end(); i++) { - i->getTo()->dependentStopped(); - } + notify_dependencies_stopped(); // Cancel start of dependents: for (sr_iter i = dependents.begin(); i != dependents.end(); i++) { @@ -716,6 +715,11 @@ void ServiceRecord::stop() noexcept } desired_state = ServiceState::STOPPED; + + if (service_state == ServiceState::STOPPED) { + notify_dependencies_stopped(); + return; + } do_stop(); } diff --git a/src/service.h b/src/service.h index 3e5211b..ffd2889 100644 --- a/src/service.h +++ b/src/service.h @@ -282,6 +282,10 @@ class ServiceRecord return waiting_for_deps && ! force_stop; } + // Notify dependencies that we no longer need them, + // (if this is actually the case). + void notify_dependencies_stopped() noexcept; + // A dependent has reached STOPPED state void dependentStopped() noexcept; -- 2.25.1