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 bool will_restart = (desired_state == service_state_t::STARTED)
54 && !services->is_shutting_down();
56 for (auto & dependency : depends_on) {
57 // we signal dependencies in case they are waiting for us to stop:
58 dependency.get_to()->dependent_stopped();
61 service_state = service_state_t::STOPPED;
64 // Desired state is "started".
72 // If we were explicitly started, our required_by count must be at least 1. Use
73 // release() to correctly release, mark inactive and release dependencies.
74 start_explicit = false;
77 else if (required_by == 0) {
78 // This can only be the case if we didn't have start_explicit, since required_by would
79 // otherwise by non-zero.
80 prop_release = !prop_require;
82 services->add_prop_queue(this);
83 services->service_inactive(this);
87 // Start failure will have been logged already, only log if we are stopped for other reasons:
89 log_service_stopped(service_name);
91 // If this service chains to another, start the other service now:
92 if (! will_restart && ! start_on_completion.empty()) {
94 auto chain_to = services->load_service(start_on_completion.c_str());
97 catch (service_load_exc &sle) {
98 log(loglevel_t::ERROR, "Couldn't chain to service ", start_on_completion, ": ",
99 "couldn't load ", sle.service_name, ": ", sle.exc_description);
101 catch (std::bad_alloc &bae) {
102 log(loglevel_t::ERROR, "Couldn't chain to service ", start_on_completion,
107 notify_listeners(service_event_t::STOPPED);
110 bool service_record::do_auto_restart() noexcept
113 return !services->is_shutting_down();
118 void service_record::require() noexcept
120 if (required_by++ == 0) {
121 prop_require = !prop_release;
122 prop_release = false;
123 services->add_prop_queue(this);
124 if (service_state != service_state_t::STARTING && service_state != service_state_t::STARTED) {
130 void service_record::release(bool issue_stop) noexcept
132 if (--required_by == 0) {
133 desired_state = service_state_t::STOPPED;
135 // Can stop, and can release dependencies now. We don't need to issue a release if
136 // the require was pending though:
137 prop_release = !prop_require;
138 prop_require = false;
139 services->add_prop_queue(this);
141 if (service_state == service_state_t::STOPPED) {
142 services->service_inactive(this);
144 else if (issue_stop) {
145 stop_reason = stopped_reason_t::NORMAL;
151 void service_record::release_dependencies() noexcept
153 for (auto & dependency : depends_on) {
154 service_record * dep_to = dependency.get_to();
155 if (dependency.holding_acq) {
156 // We must clear holding_acq before calling release, otherwise the dependency
157 // may decide to stop, check this link and release itself a second time.
158 dependency.holding_acq = false;
164 void service_record::start(bool activate) noexcept
166 if (activate && ! start_explicit) {
168 start_explicit = true;
171 if (desired_state == service_state_t::STARTED && service_state != service_state_t::STOPPED) return;
173 bool was_active = service_state != service_state_t::STOPPED || desired_state != service_state_t::STOPPED;
174 desired_state = service_state_t::STARTED;
176 if (service_state != service_state_t::STOPPED) {
177 // We're already starting/started, or we are stopping and need to wait for
178 // that the complete.
179 if (service_state != service_state_t::STOPPING || ! can_interrupt_stop()) {
182 // We're STOPPING, and that can be interrupted. Our dependencies might be STOPPING,
183 // but if so they are waiting (for us), so they too can be instantly returned to
185 notify_listeners(service_event_t::STOPCANCELLED);
187 else if (! was_active) {
188 services->service_active(this);
191 start_failed = false;
192 start_skipped = false;
193 service_state = service_state_t::STARTING;
194 waiting_for_deps = true;
196 if (start_check_dependencies()) {
197 services->add_transition_queue(this);
201 void service_record::do_propagation() noexcept
204 // Need to require all our dependencies
205 for (auto & dep : depends_on) {
206 dep.get_to()->require();
207 dep.holding_acq = true;
209 prop_require = false;
213 release_dependencies();
214 prop_release = false;
218 prop_failure = false;
219 stop_reason = stopped_reason_t::DEPFAILED;
220 failed_to_start(true);
234 void service_record::execute_transition() noexcept
236 // state is STARTED with restarting set true if we are running a smooth recovery.
237 if (service_state == service_state_t::STARTING || (service_state == service_state_t::STARTED
239 if (check_deps_started()) {
243 else if (service_state == service_state_t::STOPPING) {
244 if (stop_check_dependents()) {
245 waiting_for_deps = false;
251 void service_record::do_start() noexcept
253 if (pinned_stopped) return;
255 if (service_state != service_state_t::STARTING) {
259 service_state = service_state_t::STARTING;
261 waiting_for_deps = true;
263 // Ask dependencies to start, mark them as being waited on.
264 if (check_deps_started()) {
265 // Once all dependencies are started, we start properly:
270 void service_record::dependency_started() noexcept
272 // Note that we check for STARTED state here in case the service is in smooth recovery while pinned.
273 // In that case it will wait for dependencies to start before restarting the process.
274 if ((service_state == service_state_t::STARTING || service_state == service_state_t::STARTED)
275 && waiting_for_deps) {
276 services->add_transition_queue(this);
280 bool service_record::start_check_dependencies() noexcept
282 bool all_deps_started = true;
284 for (auto & dep : depends_on) {
285 service_record * to = dep.get_to();
286 if (to->service_state != service_state_t::STARTED) {
287 if (to->service_state != service_state_t::STARTING) {
288 to->prop_start = true;
289 services->add_prop_queue(to);
291 dep.waiting_on = true;
292 all_deps_started = false;
296 return all_deps_started;
299 bool service_record::check_deps_started() noexcept
301 for (auto & dep : depends_on) {
302 if (dep.waiting_on) {
310 void service_record::all_deps_started() noexcept
312 if (onstart_flags.starts_on_console && ! have_console) {
317 waiting_for_deps = false;
319 if (! can_proceed_to_start()) {
320 waiting_for_deps = true;
324 bool start_success = bring_up();
325 if (! start_success) {
330 void service_record::acquired_console() noexcept
332 waiting_for_console = false;
335 if (service_state != service_state_t::STARTING) {
336 // We got the console but no longer want it.
339 else if (check_deps_started()) {
343 // We got the console but can't use it yet.
348 void service_record::started() noexcept
350 // If we start on console but don't keep it, release it now:
351 if (have_console && ! onstart_flags.runs_on_console) {
352 bp_sys::tcsetpgrp(0, bp_sys::getpgrp());
356 log_service_started(get_name());
357 service_state = service_state_t::STARTED;
358 notify_listeners(service_event_t::STARTED);
360 if (onstart_flags.rw_ready) {
363 if (onstart_flags.log_ready) {
364 setup_external_log();
367 if (force_stop || desired_state == service_state_t::STOPPED) {
373 // Notify any dependents whose desired state is STARTED:
374 for (auto dept : dependents) {
375 dept->get_from()->dependency_started();
376 dept->waiting_on = false;
380 void service_record::failed_to_start(bool depfailed, bool immediate_stop) noexcept
382 if (waiting_for_console) {
383 services->unqueue_console(this);
384 waiting_for_console = false;
387 if (start_explicit) {
388 start_explicit = false;
392 // Cancel start of dependents:
393 for (auto & dept : dependents) {
394 switch (dept->dep_type) {
395 case dependency_type::REGULAR:
396 case dependency_type::MILESTONE:
397 if (dept->get_from()->service_state == service_state_t::STARTING) {
398 dept->get_from()->prop_failure = true;
399 services->add_prop_queue(dept->get_from());
402 case dependency_type::WAITS_FOR:
403 case dependency_type::SOFT:
404 if (dept->waiting_on) {
405 dept->waiting_on = false;
406 dept->get_from()->dependency_started();
410 // Always release now, so that our desired state will be STOPPED before we call
411 // stopped() below (if we do so). Otherwise it may decide to restart us.
412 if (dept->holding_acq) {
413 dept->holding_acq = false;
419 log_service_failed(get_name());
420 notify_listeners(service_event_t::FAILEDSTART);
422 if (immediate_stop) {
427 bool service_record::bring_up() noexcept
429 // default implementation: there is no process, so we are started.
434 // Mark this and all dependent services as force-stopped.
435 void service_record::forced_stop() noexcept
437 if (service_state != service_state_t::STOPPED) {
439 if (! pinned_started) {
441 services->add_prop_queue(this);
446 void service_record::dependent_stopped() noexcept
448 if (service_state == service_state_t::STOPPING && waiting_for_deps) {
449 services->add_transition_queue(this);
453 void service_record::stop(bool bring_down) noexcept
455 if (start_explicit) {
456 start_explicit = false;
460 // If our required_by count is 0, we should treat this as a full manual stop regardless
461 if (required_by == 0) bring_down = true;
463 // If it's a manual bring-down, we'll also break holds from waits-for dependencies, to avoid
464 // bouncing back up again -- but only if all holds are from waits-for dependencies.
466 if (std::all_of(dependents.begin(), dependents.end(), [](service_dep * x) {
467 return x->dep_type == dependency_type::WAITS_FOR || x->dep_type == dependency_type::SOFT; }))
469 for (auto dept : dependents) {
470 if (dept->waiting_on) {
471 dept->waiting_on = false;
472 dept->get_from()->dependency_started();
474 if (dept->holding_acq) {
475 dept->holding_acq = false;
476 // release without issuing stop, since we issue stop if necessary below
483 if (bring_down && service_state != service_state_t::STOPPED
484 && service_state != service_state_t::STOPPING) {
485 stop_reason = stopped_reason_t::NORMAL;
490 void service_record::do_stop() noexcept
492 // A service that does actually stop for any reason should have its explicit activation released, unless
494 if (start_explicit && ! do_auto_restart()) {
495 start_explicit = false;
499 bool all_deps_stopped = stop_dependents();
501 if (service_state != service_state_t::STARTED) {
502 if (service_state == service_state_t::STARTING) {
503 // If waiting for a dependency, or waiting for the console, we can interrupt start. Otherwise,
504 // we need to delegate to can_interrupt_start() (which can be overridden).
505 if (! waiting_for_deps && ! waiting_for_console) {
506 if (! can_interrupt_start()) {
507 // Well this is awkward: we're going to have to continue starting. We can stop once
508 // we've reached the started state.
512 if (! interrupt_start()) {
513 // Now wait for service startup to actually end; we don't need to handle it here.
514 notify_listeners(service_event_t::STARTCANCELLED);
518 else if (waiting_for_console) {
519 services->unqueue_console(this);
520 waiting_for_console = false;
523 // We must have had desired_state == STARTED.
524 notify_listeners(service_event_t::STARTCANCELLED);
526 // Reaching this point, we are starting interruptibly - so we
527 // stop now (by falling through to below).
530 // If we're starting we need to wait for that to complete.
531 // If we're already stopping/stopped there's nothing to do.
536 if (pinned_started) return;
538 service_state = service_state_t::STOPPING;
539 waiting_for_deps = true;
540 if (all_deps_stopped) {
541 services->add_transition_queue(this);
545 bool service_record::stop_check_dependents() noexcept
547 bool all_deps_stopped = true;
548 for (auto dept : dependents) {
549 if (dept->dep_type == dependency_type::REGULAR && ! dept->get_from()->is_stopped()) {
550 all_deps_stopped = false;
555 return all_deps_stopped;
558 bool service_record::stop_dependents() noexcept
560 bool all_deps_stopped = true;
561 for (auto dept : dependents) {
562 if (dept->dep_type == dependency_type::REGULAR ||
563 (dept->dep_type == dependency_type::MILESTONE &&
564 dept->get_from()->service_state != service_state_t::STARTED)) {
565 if (! dept->get_from()->is_stopped()) {
566 // Note we check *first* since if the dependent service is not stopped,
567 // 1. We will issue a stop to it shortly and
568 // 2. It will notify us when stopped, at which point the stop_check_dependents()
569 // check is run anyway.
570 all_deps_stopped = false;
574 // If this service is to be forcefully stopped, dependents must also be.
575 dept->get_from()->forced_stop();
578 dept->get_from()->prop_stop = true;
579 services->add_prop_queue(dept->get_from());
582 // waits-for or soft dependency:
583 if (dept->waiting_on) {
584 dept->waiting_on = false;
585 dept->get_from()->dependency_started();
587 if (dept->holding_acq && !auto_restart) {
588 dept->holding_acq = false;
589 // release without issuing stop, since we should be called only when this
590 // service is already stopped/stopping:
596 return all_deps_stopped;
599 // All dependents have stopped; we can stop now, too. Only called when STOPPING.
600 void service_record::bring_down() noexcept
602 waiting_for_deps = false;
606 void service_record::unpin() noexcept
608 if (pinned_started) {
609 pinned_started = false;
610 if (desired_state == service_state_t::STOPPED || force_stop) {
612 services->process_queues();
615 if (pinned_stopped) {
616 pinned_stopped = false;
617 if (desired_state == service_state_t::STARTED) {
619 services->process_queues();
624 void service_record::queue_for_console() noexcept
626 waiting_for_console = true;
627 services->append_console_queue(this);
630 void service_record::release_console() noexcept
632 have_console = false;
633 services->pull_console_queue();
636 bool service_record::interrupt_start() noexcept
641 void service_set::service_active(service_record *sr) noexcept
646 void service_set::service_inactive(service_record *sr) noexcept