b516c4421b4c3ce57a20ceca8d607c9422a4a202
[oweals/dinit.git] / src / service.cc
1 #include <cstring>
2 #include <cerrno>
3 #include <iterator>
4 #include <memory>
5 #include <cstddef>
6
7 #include <sys/ioctl.h>
8 #include <fcntl.h>
9 #include <termios.h>
10
11 #include "dinit.h"
12 #include "service.h"
13 #include "dinit-log.h"
14 #include "dinit-socket.h"
15 #include "dinit-util.h"
16 #include "baseproc-sys.h"
17
18 /*
19  * service.cc - Service management.
20  * See service.h for details.
21  */
22
23 // Find the requested service by name
24 static service_record * find_service(const std::list<service_record *> & records,
25                                     const char *name) noexcept
26 {
27     using std::list;
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) {
31             return *i;
32         }
33     }
34     return nullptr;
35 }
36
37 service_record * service_set::find_service(const std::string &name) noexcept
38 {
39     return ::find_service(records, name.c_str());
40 }
41
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
45 {
46     if (have_console) {
47         bp_sys::tcsetpgrp(0, bp_sys::getpgrp());
48         release_console();
49     }
50
51     force_stop = false;
52
53     bool will_restart = (desired_state == service_state_t::STARTED)
54             && !services->is_shutting_down();
55
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();
59     }
60
61     service_state = service_state_t::STOPPED;
62
63     if (will_restart) {
64         // Desired state is "started".
65         restarting = true;
66         start(false);
67     }
68     else {
69         becoming_inactive();
70         
71         if (start_explicit) {
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;
75             release();
76         }
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;
81             prop_require = false;
82             services->add_prop_queue(this);
83             services->service_inactive(this);
84         }
85     }
86
87     // Start failure will have been logged already, only log if we are stopped for other reasons:
88     if (! start_failed) {
89         log_service_stopped(service_name);
90
91         // If this service chains to another, start the other service now:
92         if (! will_restart && ! start_on_completion.empty()) {
93             try {
94                 auto chain_to = services->load_service(start_on_completion.c_str());
95                 chain_to->start();
96             }
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);
100             }
101             catch (std::bad_alloc &bae) {
102                 log(loglevel_t::ERROR, "Couldn't chain to service ", start_on_completion,
103                         ": Out of memory");
104             }
105         }
106     }
107     notify_listeners(service_event_t::STOPPED);
108 }
109
110 bool service_record::do_auto_restart() noexcept
111 {
112     if (auto_restart) {
113         return !services->is_shutting_down();
114     }
115     return false;
116 }
117
118 void service_record::require() noexcept
119 {
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) {
125             prop_start = true;
126         }
127     }
128 }
129
130 void service_record::release(bool issue_stop) noexcept
131 {
132     if (--required_by == 0) {
133         desired_state = service_state_t::STOPPED;
134
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);
140
141         if (service_state == service_state_t::STOPPED) {
142             services->service_inactive(this);
143         }
144         else if (issue_stop) {
145                 stop_reason = stopped_reason_t::NORMAL;
146             do_stop();
147         }
148     }
149 }
150
151 void service_record::release_dependencies() noexcept
152 {
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;
159             dep_to->release();
160         }
161     }
162 }
163
164 void service_record::start(bool activate) noexcept
165 {
166     if (activate && ! start_explicit) {
167         require();
168         start_explicit = true;
169     }
170     
171     if (desired_state == service_state_t::STARTED && service_state != service_state_t::STOPPED) return;
172
173     bool was_active = service_state != service_state_t::STOPPED || desired_state != service_state_t::STOPPED;
174     desired_state = service_state_t::STARTED;
175     
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()) {
180             return;
181         }
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
184         // STARTING state.
185         notify_listeners(service_event_t::STOPCANCELLED);
186     }
187     else if (! was_active) {
188         services->service_active(this);
189     }
190
191     start_failed = false;
192     start_skipped = false;
193     service_state = service_state_t::STARTING;
194     waiting_for_deps = true;
195
196     if (start_check_dependencies()) {
197         services->add_transition_queue(this);
198     }
199 }
200
201 void service_record::do_propagation() noexcept
202 {
203     if (prop_require) {
204         // Need to require all our dependencies
205         for (auto & dep : depends_on) {
206             dep.get_to()->require();
207             dep.holding_acq = true;
208         }
209         prop_require = false;
210     }
211     
212     if (prop_release) {
213         release_dependencies();
214         prop_release = false;
215     }
216     
217     if (prop_failure) {
218         prop_failure = false;
219         stop_reason = stopped_reason_t::DEPFAILED;
220         failed_to_start(true);
221     }
222     
223     if (prop_start) {
224         prop_start = false;
225         start(false);
226     }
227
228     if (prop_stop) {
229         prop_stop = false;
230         do_stop();
231     }
232 }
233
234 void service_record::execute_transition() noexcept
235 {
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
238             && restarting)) {
239         if (check_deps_started()) {
240             all_deps_started();
241         }
242     }
243     else if (service_state == service_state_t::STOPPING) {
244         if (stop_check_dependents()) {
245             waiting_for_deps = false;
246             bring_down();
247         }
248     }
249 }
250
251 void service_record::do_start() noexcept
252 {
253     if (pinned_stopped) return;
254     
255     if (service_state != service_state_t::STARTING) {
256         return;
257     }
258     
259     service_state = service_state_t::STARTING;
260
261     waiting_for_deps = true;
262
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:
266         all_deps_started();
267     }
268 }
269
270 void service_record::dependency_started() noexcept
271 {
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);
277     }
278 }
279
280 bool service_record::start_check_dependencies() noexcept
281 {
282     bool all_deps_started = true;
283
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);
290             }
291             dep.waiting_on = true;
292             all_deps_started = false;
293         }
294     }
295     
296     return all_deps_started;
297 }
298
299 bool service_record::check_deps_started() noexcept
300 {
301     for (auto & dep : depends_on) {
302         if (dep.waiting_on) {
303             return false;
304         }
305     }
306
307     return true;
308 }
309
310 void service_record::all_deps_started() noexcept
311 {
312     if (onstart_flags.starts_on_console && ! have_console) {
313         queue_for_console();
314         return;
315     }
316     
317     waiting_for_deps = false;
318
319     if (! can_proceed_to_start()) {
320         waiting_for_deps = true;
321         return;
322     }
323
324     bool start_success = bring_up();
325     if (! start_success) {
326         failed_to_start();
327     }
328 }
329
330 void service_record::acquired_console() noexcept
331 {
332     waiting_for_console = false;
333     have_console = true;
334
335     if (service_state != service_state_t::STARTING) {
336         // We got the console but no longer want it.
337         release_console();
338     }
339     else if (check_deps_started()) {
340         all_deps_started();
341     }
342     else {
343         // We got the console but can't use it yet.
344         release_console();
345     }
346 }
347
348 void service_record::started() noexcept
349 {
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());
353         release_console();
354     }
355
356     log_service_started(get_name());
357     service_state = service_state_t::STARTED;
358     notify_listeners(service_event_t::STARTED);
359
360     if (onstart_flags.rw_ready) {
361         rootfs_is_rw();
362     }
363     if (onstart_flags.log_ready) {
364         setup_external_log();
365     }
366
367     if (force_stop || desired_state == service_state_t::STOPPED) {
368         // We must now stop.
369         do_stop();
370         return;
371     }
372
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;
377     }
378 }
379
380 void service_record::failed_to_start(bool depfailed, bool immediate_stop) noexcept
381 {
382     if (waiting_for_console) {
383         services->unqueue_console(this);
384         waiting_for_console = false;
385     }
386
387     if (start_explicit) {
388         start_explicit = false;
389         release(false);
390     }
391
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());
400             }
401             break;
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();
407             }
408         }
409
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;
414             release(false);
415         }
416     }
417
418     start_failed = true;
419     log_service_failed(get_name());
420     notify_listeners(service_event_t::FAILEDSTART);
421
422     if (immediate_stop) {
423         stopped();
424     }
425 }
426
427 bool service_record::bring_up() noexcept
428 {
429     // default implementation: there is no process, so we are started.
430     started();
431     return true;
432 }
433
434 // Mark this and all dependent services as force-stopped.
435 void service_record::forced_stop() noexcept
436 {
437     if (service_state != service_state_t::STOPPED) {
438         force_stop = true;
439         if (! pinned_started) {
440             prop_stop = true;
441             services->add_prop_queue(this);
442         }
443     }
444 }
445
446 void service_record::dependent_stopped() noexcept
447 {
448     if (service_state == service_state_t::STOPPING && waiting_for_deps) {
449         services->add_transition_queue(this);
450     }
451 }
452
453 void service_record::stop(bool bring_down) noexcept
454 {
455     if (start_explicit) {
456         start_explicit = false;
457         release();
458     }
459
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;
462
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.
465     if (bring_down) {
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; }))
468         {
469             for (auto dept : dependents) {
470                 if (dept->waiting_on) {
471                     dept->waiting_on = false;
472                     dept->get_from()->dependency_started();
473                 }
474                 if (dept->holding_acq) {
475                     dept->holding_acq = false;
476                     // release without issuing stop, since we issue stop if necessary below
477                     release(false);
478                 }
479             }
480         }
481     }
482
483     if (bring_down && service_state != service_state_t::STOPPED
484                 && service_state != service_state_t::STOPPING) {
485         stop_reason = stopped_reason_t::NORMAL;
486         do_stop();
487     }
488 }
489
490 void service_record::do_stop() noexcept
491 {
492     // A service that does actually stop for any reason should have its explicit activation released, unless
493     // it will restart:
494     if (start_explicit && ! do_auto_restart()) {
495         start_explicit = false;
496         release(false);
497     }
498
499     bool all_deps_stopped = stop_dependents();
500
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.
509                     return;
510                 }
511
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);
515                     return;
516                 }
517             }
518             else if (waiting_for_console) {
519                 services->unqueue_console(this);
520                 waiting_for_console = false;
521             }
522
523             // We must have had desired_state == STARTED.
524             notify_listeners(service_event_t::STARTCANCELLED);
525
526             // Reaching this point, we are starting interruptibly - so we
527             // stop now (by falling through to below).
528         }
529         else {
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.
532             return;
533         }
534     }
535
536     if (pinned_started) return;
537
538     service_state = service_state_t::STOPPING;
539     waiting_for_deps = true;
540     if (all_deps_stopped) {
541         services->add_transition_queue(this);
542     }
543 }
544
545 bool service_record::stop_check_dependents() noexcept
546 {
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;
551             break;
552         }
553     }
554     
555     return all_deps_stopped;
556 }
557
558 bool service_record::stop_dependents() noexcept
559 {
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;
571             }
572
573             if (force_stop) {
574                 // If this service is to be forcefully stopped, dependents must also be.
575                 dept->get_from()->forced_stop();
576             }
577
578             dept->get_from()->prop_stop = true;
579             services->add_prop_queue(dept->get_from());
580         }
581         else {
582             // waits-for or soft dependency:
583             if (dept->waiting_on) {
584                 dept->waiting_on = false;
585                 dept->get_from()->dependency_started();
586             }
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:
591                 release(false);
592             }
593         }
594     }
595
596     return all_deps_stopped;
597 }
598
599 // All dependents have stopped; we can stop now, too. Only called when STOPPING.
600 void service_record::bring_down() noexcept
601 {
602     waiting_for_deps = false;
603     stopped();
604 }
605
606 void service_record::unpin() noexcept
607 {
608     if (pinned_started) {
609         pinned_started = false;
610         if (desired_state == service_state_t::STOPPED || force_stop) {
611             do_stop();
612             services->process_queues();
613         }
614     }
615     if (pinned_stopped) {
616         pinned_stopped = false;
617         if (desired_state == service_state_t::STARTED) {
618             do_start();
619             services->process_queues();
620         }
621     }
622 }
623
624 void service_record::queue_for_console() noexcept
625 {
626     waiting_for_console = true;
627     services->append_console_queue(this);
628 }
629
630 void service_record::release_console() noexcept
631 {
632     have_console = false;
633     services->pull_console_queue();
634 }
635
636 bool service_record::interrupt_start() noexcept
637 {
638     return true;
639 }
640
641 void service_set::service_active(service_record *sr) noexcept
642 {
643     active_services++;
644 }
645
646 void service_set::service_inactive(service_record *sr) noexcept
647 {
648     active_services--;
649 }