13 #include "dinit-log.h"
14 #include "dinit-socket.h"
15 #include "dinit-util.h"
16 #include "baseproc-sys.h"
19 * service.cc - Service management.
20 * See service.h for details.
23 // Find the requested service by name
24 static service_record * find_service(const std::list<service_record *> & records,
25 const char *name) noexcept
28 list<service_record *>::const_iterator i = records.begin();
29 for ( ; i != records.end(); ++i ) {
30 if (strcmp((*i)->get_name().c_str(), name) == 0) {
37 service_record * service_set::find_service(const std::string &name) noexcept
39 return ::find_service(records, name.c_str());
42 // Called when a service has actually stopped; dependents have stopped already, unless this stop
43 // is due to an unexpected process termination.
44 void service_record::stopped() noexcept
47 bp_sys::tcsetpgrp(0, bp_sys::getpgrp());
53 // If we are to re-start, restarting should have been set true and desired_state should be STARTED.
54 // (A restart could be cancelled via a separately issued stop, including via a shutdown).
55 restarting |= auto_restart;
56 bool will_restart = restarting && desired_state == service_state_t::STARTED;
57 if (restarting && ! will_restart) {
58 notify_listeners(service_event_t::STARTCANCELLED);
62 // If we won't restart, break soft dependencies now
64 for (auto dept : dependents) {
65 if (! dept->is_hard()) {
66 // waits-for or soft dependency:
67 if (dept->waiting_on) {
68 dept->waiting_on = false;
69 dept->get_from()->dependency_started();
71 if (dept->holding_acq) {
72 dept->holding_acq = false;
73 // release without issuing stop, since we're called only when this
74 // service is already stopped/stopping:
81 for (auto & dependency : depends_on) {
82 // we signal dependencies in case they are waiting for us to stop:
83 dependency.get_to()->dependent_stopped();
86 service_state = service_state_t::STOPPED;
89 // Desired state is "started".
97 // If we were explicitly started, our required_by count must be at least 1. Use
98 // release() to correctly release, mark inactive and release dependencies.
99 start_explicit = false;
102 else if (required_by == 0) {
103 // This can only be the case if we didn't have start_explicit, since required_by would
104 // otherwise by non-zero.
105 prop_release = !prop_require;
106 prop_require = false;
107 services->add_prop_queue(this);
108 services->service_inactive(this);
112 // Start failure will have been logged already, only log if we are stopped for other reasons:
113 if (! start_failed) {
114 log_service_stopped(service_name);
116 // If this service chains to another, start the other service now:
117 if (! will_restart && ! start_on_completion.empty()) {
119 auto chain_to = services->load_service(start_on_completion.c_str());
122 catch (service_load_exc &sle) {
123 log(loglevel_t::ERROR, "Couldn't chain to service ", start_on_completion, ": ",
124 "couldn't load ", sle.service_name, ": ", sle.exc_description);
126 catch (std::bad_alloc &bae) {
127 log(loglevel_t::ERROR, "Couldn't chain to service ", start_on_completion,
132 notify_listeners(service_event_t::STOPPED);
135 void service_record::require() noexcept
137 if (required_by++ == 0) {
138 prop_require = !prop_release;
139 prop_release = false;
140 services->add_prop_queue(this);
141 if (service_state != service_state_t::STARTING && service_state != service_state_t::STARTED) {
147 void service_record::release(bool issue_stop) noexcept
149 if (--required_by == 0) {
150 desired_state = service_state_t::STOPPED;
151 prop_require = false;
153 // Can stop, and can release dependencies now. We don't need to issue a release if
154 // the require was pending though:
155 if (service_state != service_state_t::STOPPED && service_state != service_state_t::STOPPING) {
156 prop_release = !prop_require;
157 prop_require = false;
158 services->add_prop_queue(this);
161 if (service_state == service_state_t::STOPPED) {
162 services->service_inactive(this);
164 else if (issue_stop) {
165 stop_reason = stopped_reason_t::NORMAL;
171 void service_record::release_dependencies() noexcept
173 for (auto & dependency : depends_on) {
174 service_record * dep_to = dependency.get_to();
175 if (dependency.holding_acq) {
176 // We must clear holding_acq before calling release, otherwise the dependency
177 // may decide to stop, check this link and release itself a second time.
178 dependency.holding_acq = false;
184 void service_record::start(bool activate) noexcept
186 if (activate && ! start_explicit) {
188 start_explicit = true;
191 bool was_active = service_state != service_state_t::STOPPED || desired_state != service_state_t::STOPPED;
192 desired_state = service_state_t::STARTED;
194 if (service_state != service_state_t::STOPPED) {
195 // We're already starting/started, or we are stopping and need to wait for
196 // that the complete.
197 if (service_state != service_state_t::STOPPING) {
201 if (! can_interrupt_stop()) {
206 // We're STOPPING, and that can be interrupted. Our dependencies might be STOPPING,
207 // but if so they are waiting (for us), so they too can be instantly returned to
209 notify_listeners(service_event_t::STOPCANCELLED);
211 else if (! was_active) {
212 services->service_active(this);
215 start_failed = false;
216 start_skipped = false;
217 service_state = service_state_t::STARTING;
218 waiting_for_deps = true;
220 if (start_check_dependencies()) {
221 services->add_transition_queue(this);
225 void service_record::do_propagation() noexcept
228 // Need to require all our dependencies
229 for (auto & dep : depends_on) {
230 dep.get_to()->require();
231 dep.holding_acq = true;
233 prop_require = false;
237 release_dependencies();
238 prop_release = false;
242 prop_failure = false;
243 stop_reason = stopped_reason_t::DEPFAILED;
244 failed_to_start(true);
258 void service_record::execute_transition() noexcept
260 // state is STARTED with restarting set true if we are running a smooth recovery.
261 if (service_state == service_state_t::STARTING || (service_state == service_state_t::STARTED
263 if (check_deps_started()) {
267 else if (service_state == service_state_t::STOPPING) {
268 if (stop_check_dependents()) {
269 waiting_for_deps = false;
271 // A service that does actually stop for any reason should have its explicit activation released, unless
273 if (start_explicit && !auto_restart && !restarting) {
274 start_explicit = false;
283 void service_record::do_start() noexcept
285 if (pinned_stopped) return;
287 if (service_state != service_state_t::STARTING) {
291 service_state = service_state_t::STARTING;
293 waiting_for_deps = true;
295 // Ask dependencies to start, mark them as being waited on.
296 if (check_deps_started()) {
297 // Once all dependencies are started, we start properly:
302 void service_record::dependency_started() noexcept
304 // Note that we check for STARTED state here in case the service is in smooth recovery while pinned.
305 // In that case it will wait for dependencies to start before restarting the process.
306 if ((service_state == service_state_t::STARTING || service_state == service_state_t::STARTED)
307 && waiting_for_deps) {
308 services->add_transition_queue(this);
312 bool service_record::start_check_dependencies() noexcept
314 bool all_deps_started = true;
316 for (auto & dep : depends_on) {
317 service_record * to = dep.get_to();
318 if (to->service_state != service_state_t::STARTED) {
319 if (to->service_state != service_state_t::STARTING) {
320 to->prop_start = true;
321 services->add_prop_queue(to);
323 dep.waiting_on = true;
324 all_deps_started = false;
328 return all_deps_started;
331 bool service_record::check_deps_started() noexcept
333 for (auto & dep : depends_on) {
334 if (dep.waiting_on) {
342 void service_record::all_deps_started() noexcept
344 if (onstart_flags.starts_on_console && ! have_console) {
349 waiting_for_deps = false;
351 if (! can_proceed_to_start()) {
352 waiting_for_deps = true;
356 bool start_success = bring_up();
358 if (! start_success) {
363 void service_record::acquired_console() noexcept
365 waiting_for_console = false;
368 if (service_state != service_state_t::STARTING) {
369 // We got the console but no longer want it.
372 else if (check_deps_started()) {
376 // We got the console but can't use it yet.
381 void service_record::started() noexcept
383 // If we start on console but don't keep it, release it now:
384 if (have_console && ! onstart_flags.runs_on_console) {
385 bp_sys::tcsetpgrp(0, bp_sys::getpgrp());
389 log_service_started(get_name());
390 service_state = service_state_t::STARTED;
391 notify_listeners(service_event_t::STARTED);
393 if (onstart_flags.rw_ready) {
396 if (onstart_flags.log_ready) {
397 setup_external_log();
400 if (force_stop || desired_state == service_state_t::STOPPED) {
406 // Notify any dependents whose desired state is STARTED:
407 for (auto dept : dependents) {
408 dept->get_from()->dependency_started();
409 dept->waiting_on = false;
413 void service_record::failed_to_start(bool depfailed, bool immediate_stop) noexcept
415 if (waiting_for_console) {
416 services->unqueue_console(this);
417 waiting_for_console = false;
420 if (start_explicit) {
421 start_explicit = false;
425 // Cancel start of dependents:
426 for (auto & dept : dependents) {
427 switch (dept->dep_type) {
428 case dependency_type::REGULAR:
429 case dependency_type::MILESTONE:
430 if (dept->get_from()->service_state == service_state_t::STARTING) {
431 dept->get_from()->prop_failure = true;
432 services->add_prop_queue(dept->get_from());
435 case dependency_type::WAITS_FOR:
436 case dependency_type::SOFT:
437 if (dept->waiting_on) {
438 dept->waiting_on = false;
439 dept->get_from()->dependency_started();
443 // Always release now, so that our desired state will be STOPPED before we call
444 // stopped() below (if we do so). Otherwise it may decide to restart us.
445 if (dept->holding_acq) {
446 dept->holding_acq = false;
452 log_service_failed(get_name());
453 notify_listeners(service_event_t::FAILEDSTART);
455 if (immediate_stop) {
460 bool service_record::bring_up() noexcept
462 // default implementation: there is no process, so we are started.
467 // Mark this and all dependent services as force-stopped.
468 void service_record::forced_stop() noexcept
470 if (service_state != service_state_t::STOPPED) {
472 if (! pinned_started) {
474 services->add_prop_queue(this);
479 void service_record::dependent_stopped() noexcept
481 if (service_state == service_state_t::STOPPING && waiting_for_deps) {
482 services->add_transition_queue(this);
486 void service_record::stop(bool bring_down) noexcept
488 if (start_explicit) {
489 start_explicit = false;
493 // If our required_by count is 0, we should treat this as a full manual stop regardless
494 if (required_by == 0) {
498 // Set desired state to STOPPED, this will be set back to STARTED if there any hard dependents
499 // that want to restart.
500 desired_state = service_state_t::STOPPED;
502 if (bring_down && service_state != service_state_t::STOPPED
503 && service_state != service_state_t::STOPPING) {
504 stop_reason = stopped_reason_t::NORMAL;
509 bool service_record::restart() noexcept
511 // Re-start without affecting dependency links/activation.
513 if (service_state == service_state_t::STARTED) {
515 stop_reason = stopped_reason_t::NORMAL;
524 void service_record::do_stop() noexcept
526 // Called when we should definitely stop. We may need to restart afterwards, but we
527 // won't know that for sure until the execution transition.
529 bool all_deps_stopped = stop_dependents();
531 if (service_state != service_state_t::STARTED) {
532 if (service_state == service_state_t::STARTING) {
533 // If waiting for a dependency, or waiting for the console, we can interrupt start. Otherwise,
534 // we need to delegate to can_interrupt_start() (which can be overridden).
535 if (! waiting_for_deps && ! waiting_for_console) {
536 if (! can_interrupt_start()) {
537 // Well this is awkward: we're going to have to continue starting. We can stop once
538 // we've reached the started state.
542 if (! interrupt_start()) {
543 // Now wait for service startup to actually end; we don't need to handle it here.
544 notify_listeners(service_event_t::STARTCANCELLED);
548 else if (waiting_for_console) {
549 services->unqueue_console(this);
550 waiting_for_console = false;
553 // We must have had desired_state == STARTED.
554 notify_listeners(service_event_t::STARTCANCELLED);
556 // Reaching this point, we are starting interruptibly - so we
557 // stop now (by falling through to below).
560 // If we're starting we need to wait for that to complete.
561 // If we're already stopping/stopped there's nothing to do.
566 if (pinned_started) return;
568 service_state = service_state_t::STOPPING;
569 waiting_for_deps = true;
570 if (all_deps_stopped) {
571 services->add_transition_queue(this);
575 bool service_record::stop_check_dependents() noexcept
577 bool all_deps_stopped = true;
578 for (auto dept : dependents) {
579 if (dept->is_hard() && dept->holding_acq) {
580 all_deps_stopped = false;
585 return all_deps_stopped;
588 bool service_record::stop_dependents() noexcept
590 bool all_deps_stopped = true;
591 for (auto dept : dependents) {
592 if (dept->is_hard() && dept->holding_acq) {
593 if (! dept->get_from()->is_stopped()) {
594 // Note we check *first* since if the dependent service is not stopped,
595 // 1. We will issue a stop to it shortly and
596 // 2. It will notify us when stopped, at which point the stop_check_dependents()
597 // check is run anyway.
598 all_deps_stopped = false;
602 // If this service is to be forcefully stopped, dependents must also be.
603 dept->get_from()->forced_stop();
606 dept->get_from()->prop_stop = true;
607 services->add_prop_queue(dept->get_from());
609 // Note that soft dependencies are held (for now). If we restart, we don't want those dependencies
613 return all_deps_stopped;
616 // All dependents have stopped; we can stop now, too. Only called when STOPPING.
617 void service_record::bring_down() noexcept
619 waiting_for_deps = false;
623 void service_record::unpin() noexcept
625 if (pinned_started) {
626 pinned_started = false;
628 for (auto &dep : depends_on) {
630 if (dep.get_to()->get_state() != service_state_t::STARTED) {
631 desired_state = service_state_t::STOPPED;
634 else if (dep.holding_acq) {
635 dep.holding_acq = false;
636 dep.get_to()->release();
640 if (desired_state == service_state_t::STOPPED || force_stop) {
642 services->process_queues();
645 if (pinned_stopped) {
646 pinned_stopped = false;
647 if (desired_state == service_state_t::STARTED) {
649 services->process_queues();
654 void service_record::queue_for_console() noexcept
656 waiting_for_console = true;
657 services->append_console_queue(this);
660 void service_record::release_console() noexcept
662 have_console = false;
663 services->pull_console_queue();
666 bool service_record::interrupt_start() noexcept
671 void service_set::service_active(service_record *sr) noexcept
676 void service_set::service_inactive(service_record *sr) noexcept