Fix mistakes in cptest asserts
[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     // 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);
59     }
60     restarting = false;
61
62     // If we won't restart, break soft dependencies now
63     if (! will_restart) {
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();
70                 }
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:
75                     release(false);
76                 }
77             }
78         }
79     }
80
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();
84     }
85
86     service_state = service_state_t::STOPPED;
87
88     if (will_restart) {
89         // Desired state is "started".
90         restarting = true;
91         start(false);
92     }
93     else {
94         becoming_inactive();
95         
96         if (start_explicit) {
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;
100             release();
101         }
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);
109         }
110     }
111
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);
115
116         // If this service chains to another, start the other service now:
117         if (! will_restart && ! start_on_completion.empty()) {
118             try {
119                 auto chain_to = services->load_service(start_on_completion.c_str());
120                 chain_to->start();
121             }
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);
125             }
126             catch (std::bad_alloc &bae) {
127                 log(loglevel_t::ERROR, "Couldn't chain to service ", start_on_completion,
128                         ": Out of memory");
129             }
130         }
131     }
132     notify_listeners(service_event_t::STOPPED);
133 }
134
135 void service_record::require() noexcept
136 {
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) {
142             prop_start = true;
143         }
144     }
145 }
146
147 void service_record::release(bool issue_stop) noexcept
148 {
149     if (--required_by == 0) {
150         desired_state = service_state_t::STOPPED;
151         prop_require = false;
152
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);
159         }
160
161         if (service_state == service_state_t::STOPPED) {
162             services->service_inactive(this);
163         }
164         else if (issue_stop) {
165                 stop_reason = stopped_reason_t::NORMAL;
166             do_stop();
167         }
168     }
169 }
170
171 void service_record::release_dependencies() noexcept
172 {
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;
179             dep_to->release();
180         }
181     }
182 }
183
184 void service_record::start(bool activate) noexcept
185 {
186     if (activate && ! start_explicit) {
187         require();
188         start_explicit = true;
189     }
190
191     bool was_active = service_state != service_state_t::STOPPED || desired_state != service_state_t::STOPPED;
192     desired_state = service_state_t::STARTED;
193     
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) {
198             return;
199         }
200
201         if (! can_interrupt_stop()) {
202             restarting = true;
203             return;
204         }
205
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
208         // STARTING state.
209         notify_listeners(service_event_t::STOPCANCELLED);
210     }
211     else if (! was_active) {
212         services->service_active(this);
213     }
214
215     start_failed = false;
216     start_skipped = false;
217     service_state = service_state_t::STARTING;
218     waiting_for_deps = true;
219
220     if (start_check_dependencies()) {
221         services->add_transition_queue(this);
222     }
223 }
224
225 void service_record::do_propagation() noexcept
226 {
227     if (prop_require) {
228         // Need to require all our dependencies
229         for (auto & dep : depends_on) {
230             dep.get_to()->require();
231             dep.holding_acq = true;
232         }
233         prop_require = false;
234     }
235     
236     if (prop_release) {
237         release_dependencies();
238         prop_release = false;
239     }
240     
241     if (prop_failure) {
242         prop_failure = false;
243         stop_reason = stopped_reason_t::DEPFAILED;
244         failed_to_start(true);
245     }
246     
247     if (prop_start) {
248         prop_start = false;
249         start(false);
250     }
251
252     if (prop_stop) {
253         prop_stop = false;
254         do_stop();
255     }
256 }
257
258 void service_record::execute_transition() noexcept
259 {
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
262             && restarting)) {
263         if (check_deps_started()) {
264             all_deps_started();
265         }
266     }
267     else if (service_state == service_state_t::STOPPING) {
268         if (stop_check_dependents()) {
269             waiting_for_deps = false;
270
271             // A service that does actually stop for any reason should have its explicit activation released, unless
272             // it will restart:
273             if (start_explicit && !auto_restart && !restarting) {
274                 start_explicit = false;
275                 release(false);
276             }
277
278             bring_down();
279         }
280     }
281 }
282
283 void service_record::do_start() noexcept
284 {
285     if (pinned_stopped) return;
286     
287     if (service_state != service_state_t::STARTING) {
288         return;
289     }
290     
291     service_state = service_state_t::STARTING;
292
293     waiting_for_deps = true;
294
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:
298         all_deps_started();
299     }
300 }
301
302 void service_record::dependency_started() noexcept
303 {
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);
309     }
310 }
311
312 bool service_record::start_check_dependencies() noexcept
313 {
314     bool all_deps_started = true;
315
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);
322             }
323             dep.waiting_on = true;
324             all_deps_started = false;
325         }
326     }
327     
328     return all_deps_started;
329 }
330
331 bool service_record::check_deps_started() noexcept
332 {
333     for (auto & dep : depends_on) {
334         if (dep.waiting_on) {
335             return false;
336         }
337     }
338
339     return true;
340 }
341
342 void service_record::all_deps_started() noexcept
343 {
344     if (onstart_flags.starts_on_console && ! have_console) {
345         queue_for_console();
346         return;
347     }
348     
349     waiting_for_deps = false;
350
351     if (! can_proceed_to_start()) {
352         waiting_for_deps = true;
353         return;
354     }
355
356     bool start_success = bring_up();
357     restarting = false;
358     if (! start_success) {
359         failed_to_start();
360     }
361 }
362
363 void service_record::acquired_console() noexcept
364 {
365     waiting_for_console = false;
366     have_console = true;
367
368     if (service_state != service_state_t::STARTING) {
369         // We got the console but no longer want it.
370         release_console();
371     }
372     else if (check_deps_started()) {
373         all_deps_started();
374     }
375     else {
376         // We got the console but can't use it yet.
377         release_console();
378     }
379 }
380
381 void service_record::started() noexcept
382 {
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());
386         release_console();
387     }
388
389     log_service_started(get_name());
390     service_state = service_state_t::STARTED;
391     notify_listeners(service_event_t::STARTED);
392
393     if (onstart_flags.rw_ready) {
394         rootfs_is_rw();
395     }
396     if (onstart_flags.log_ready) {
397         setup_external_log();
398     }
399
400     if (force_stop || desired_state == service_state_t::STOPPED) {
401         // We must now stop.
402         do_stop();
403         return;
404     }
405
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;
410     }
411 }
412
413 void service_record::failed_to_start(bool depfailed, bool immediate_stop) noexcept
414 {
415     if (waiting_for_console) {
416         services->unqueue_console(this);
417         waiting_for_console = false;
418     }
419
420     if (start_explicit) {
421         start_explicit = false;
422         release(false);
423     }
424
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());
433             }
434             break;
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();
440             }
441         }
442
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;
447             release(false);
448         }
449     }
450
451     start_failed = true;
452     log_service_failed(get_name());
453     notify_listeners(service_event_t::FAILEDSTART);
454
455     if (immediate_stop) {
456         stopped();
457     }
458 }
459
460 bool service_record::bring_up() noexcept
461 {
462     // default implementation: there is no process, so we are started.
463     started();
464     return true;
465 }
466
467 // Mark this and all dependent services as force-stopped.
468 void service_record::forced_stop() noexcept
469 {
470     if (service_state != service_state_t::STOPPED) {
471         force_stop = true;
472         if (! pinned_started) {
473             prop_stop = true;
474             services->add_prop_queue(this);
475         }
476     }
477 }
478
479 void service_record::dependent_stopped() noexcept
480 {
481     if (service_state == service_state_t::STOPPING && waiting_for_deps) {
482         services->add_transition_queue(this);
483     }
484 }
485
486 void service_record::stop(bool bring_down) noexcept
487 {
488     if (start_explicit) {
489         start_explicit = false;
490         required_by--;
491     }
492
493     // If our required_by count is 0, we should treat this as a full manual stop regardless
494     if (required_by == 0) {
495         bring_down = true;
496     }
497
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;
501
502     if (bring_down && service_state != service_state_t::STOPPED
503                 && service_state != service_state_t::STOPPING) {
504         stop_reason = stopped_reason_t::NORMAL;
505         do_stop();
506     }
507 }
508
509 bool service_record::restart() noexcept
510 {
511     // Re-start without affecting dependency links/activation.
512
513     if (service_state == service_state_t::STARTED) {
514         restarting = true;
515         stop_reason = stopped_reason_t::NORMAL;
516         do_stop();
517         return true;
518     }
519
520     // Wrong state
521     return false;
522 }
523
524 void service_record::do_stop() noexcept
525 {
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.
528
529     bool all_deps_stopped = stop_dependents();
530
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.
539                     return;
540                 }
541
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);
545                     return;
546                 }
547             }
548             else if (waiting_for_console) {
549                 services->unqueue_console(this);
550                 waiting_for_console = false;
551             }
552
553             // We must have had desired_state == STARTED.
554             notify_listeners(service_event_t::STARTCANCELLED);
555
556             // Reaching this point, we are starting interruptibly - so we
557             // stop now (by falling through to below).
558         }
559         else {
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.
562             return;
563         }
564     }
565
566     if (pinned_started) return;
567
568     service_state = service_state_t::STOPPING;
569     waiting_for_deps = true;
570     if (all_deps_stopped) {
571         services->add_transition_queue(this);
572     }
573 }
574
575 bool service_record::stop_check_dependents() noexcept
576 {
577     bool all_deps_stopped = true;
578     for (auto dept : dependents) {
579         if (dept->is_hard() && dept->holding_acq) {
580             all_deps_stopped = false;
581             break;
582         }
583     }
584
585     return all_deps_stopped;
586 }
587
588 bool service_record::stop_dependents() noexcept
589 {
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;
599             }
600
601             if (force_stop) {
602                 // If this service is to be forcefully stopped, dependents must also be.
603                 dept->get_from()->forced_stop();
604             }
605
606             dept->get_from()->prop_stop = true;
607             services->add_prop_queue(dept->get_from());
608         }
609         // Note that soft dependencies are held (for now). If we restart, we don't want those dependencies
610         // to be broken.
611     }
612
613     return all_deps_stopped;
614 }
615
616 // All dependents have stopped; we can stop now, too. Only called when STOPPING.
617 void service_record::bring_down() noexcept
618 {
619     waiting_for_deps = false;
620     stopped();
621 }
622
623 void service_record::unpin() noexcept
624 {
625     if (pinned_started) {
626         pinned_started = false;
627
628         for (auto &dep : depends_on) {
629             if (dep.is_hard()) {
630                 if (dep.get_to()->get_state() != service_state_t::STARTED) {
631                     desired_state = service_state_t::STOPPED;
632                 }
633             }
634             else if (dep.holding_acq) {
635                 dep.holding_acq = false;
636                 dep.get_to()->release();
637             }
638         }
639
640         if (desired_state == service_state_t::STOPPED || force_stop) {
641             do_stop();
642             services->process_queues();
643         }
644     }
645     if (pinned_stopped) {
646         pinned_stopped = false;
647         if (desired_state == service_state_t::STARTED) {
648             do_start();
649             services->process_queues();
650         }
651     }
652 }
653
654 void service_record::queue_for_console() noexcept
655 {
656     waiting_for_console = true;
657     services->append_console_queue(this);
658 }
659
660 void service_record::release_console() noexcept
661 {
662     have_console = false;
663     services->pull_console_queue();
664 }
665
666 bool service_record::interrupt_start() noexcept
667 {
668     return true;
669 }
670
671 void service_set::service_active(service_record *sr) noexcept
672 {
673     active_services++;
674 }
675
676 void service_set::service_inactive(service_record *sr) noexcept
677 {
678     active_services--;
679 }