From cef233e20caf5a21c5159ca0272cf5bd7ea35dc4 Mon Sep 17 00:00:00 2001 From: Davin McCall Date: Fri, 5 Jan 2018 20:09:28 +0000 Subject: [PATCH] Allow for interrupting process startup (by sending SIGINT). --- src/service.cc | 34 +++++++++++++++++++++------------- src/service.h | 8 +++++--- src/tests/test_service.h | 4 ++-- 3 files changed, 28 insertions(+), 18 deletions(-) diff --git a/src/service.cc b/src/service.cc index bbbe37a..a3af696 100644 --- a/src/service.cc +++ b/src/service.cc @@ -1163,21 +1163,23 @@ void service_record::do_stop() noexcept if (required_by == 0) return; // release will re-call us anyway } + bool all_deps_stopped = stop_dependents(); + if (service_state != service_state_t::STARTED) { if (service_state == service_state_t::STARTING) { if (! can_interrupt_start()) { - // Well this is awkward: we're going to have to continue - // starting, but we don't want any dependents to think that - // they are still waiting to start. - // Make sure they remain stopped: - stop_dependents(); + // Well this is awkward: we're going to have to continue starting. We can stop once we've + // reached the started state. + return; + } + + if (! interrupt_start()) { + // Now wait for service startup to actually end return; } // We must have had desired_state == STARTED. notify_listeners(service_event_t::STARTCANCELLED); - - interrupt_start(); // Reaching this point, we are starting interruptibly - so we // stop now (by falling through to below). @@ -1191,7 +1193,7 @@ void service_record::do_stop() noexcept service_state = service_state_t::STOPPING; waiting_for_deps = true; - if (stop_dependents()) { + if (all_deps_stopped) { services->add_transition_queue(this); } } @@ -1368,9 +1370,10 @@ void service_record::release_console() noexcept services->pull_console_queue(); } -void service_record::interrupt_start() noexcept +bool service_record::interrupt_start() noexcept { services->unqueue_console(this); + return true; } void service_set::service_active(service_record *sr) noexcept @@ -1407,6 +1410,7 @@ base_process_service::base_process_service(service_set *sset, string name, reserved_child_watch = false; tracking_child = false; stop_timer_armed = false; + start_is_interruptible = false; } void base_process_service::do_restart() noexcept @@ -1478,20 +1482,24 @@ bool base_process_service::restart_ps_process() noexcept return true; } -void base_process_service::interrupt_start() noexcept +bool base_process_service::interrupt_start() noexcept { - // overridden in subclasses if (waiting_restart_timer) { restart_timer.stop_timer(eventLoop); waiting_restart_timer = false; + return service_record::interrupt_start(); + } + else { + log(loglevel_t::WARN, "Interrupting start of service ", get_name(), " with pid ", pid, " (with SIGINT)."); + kill_pg(SIGINT); + return false; } - service_record::interrupt_start(); } void base_process_service::kill_with_fire() noexcept { if (pid != -1) { - log(loglevel_t::WARN, "Service ", get_name(), "with pid ", pid, " exceeded allowed stop time; killing."); + log(loglevel_t::WARN, "Service ", get_name(), " with pid ", pid, " exceeded allowed stop time; killing."); kill_pg(SIGKILL); } } diff --git a/src/service.h b/src/service.h index e06eff5..f6bfed1 100644 --- a/src/service.h +++ b/src/service.h @@ -451,7 +451,9 @@ class service_record return true; } - virtual void interrupt_start() noexcept; + // Interrupt startup. Returns true if service start is fully cancelled; returns false if cancel order + // issued but service has not yet responded. + virtual bool interrupt_start() noexcept; public: @@ -669,7 +671,7 @@ class base_process_service : public service_record virtual bool can_interrupt_start() noexcept override { - return waiting_restart_timer || service_record::can_interrupt_start(); + return waiting_restart_timer || start_is_interruptible || service_record::can_interrupt_start(); } virtual bool can_proceed_to_start() noexcept override @@ -677,7 +679,7 @@ class base_process_service : public service_record return ! waiting_restart_timer; } - virtual void interrupt_start() noexcept override; + virtual bool interrupt_start() noexcept override; // Kill with SIGKILL void kill_with_fire() noexcept; diff --git a/src/tests/test_service.h b/src/tests/test_service.h index 3593cee..eeb7605 100644 --- a/src/tests/test_service.h +++ b/src/tests/test_service.h @@ -30,9 +30,9 @@ class test_service : public service_record return waiting_for_deps; } - virtual void interrupt_start() noexcept override + virtual bool interrupt_start() noexcept override { - + return true; } void started() noexcept -- 2.25.1