Fix restart after unexpected termination.
[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 void service_set::stop_service(const std::string & name) noexcept
43 {
44     service_record *record = find_service(name);
45     if (record != nullptr) {
46         record->stop();
47         process_queues();
48     }
49 }
50
51 // Called when a service has actually stopped; dependents have stopped already, unless this stop
52 // is due to an unexpected process termination.
53 void service_record::stopped() noexcept
54 {
55     if (have_console) {
56         bp_sys::tcsetpgrp(0, bp_sys::getpgrp());
57         release_console();
58     }
59
60     force_stop = false;
61
62     // If we are a soft dependency of another target, break the acquisition from that target now,
63     // so that we don't re-start:
64     for (auto & dependent : dependents) {
65         if (dependent->dep_type != dependency_type::REGULAR) {
66             if (dependent->holding_acq  && ! dependent->waiting_on) {
67                 dependent->holding_acq = false;
68                 release();
69             }
70         }
71     }
72
73     bool will_restart = (desired_state == service_state_t::STARTED)
74             && !services->is_shutting_down();
75
76     for (auto & dependency : depends_on) {
77         // we signal dependencies in case they are waiting for us to stop:
78         dependency.get_to()->dependent_stopped();
79     }
80
81     service_state = service_state_t::STOPPED;
82
83     if (will_restart) {
84         // Desired state is "started".
85         restarting = true;
86         start(false);
87     }
88     else {
89         becoming_inactive();
90         
91         if (start_explicit) {
92             // If we were explicitly started, our required_by count must be at least 1. Use
93             // release() to correctly release, mark inactive and release dependencies.
94             start_explicit = false;
95             release();
96         }
97         else if (required_by == 0) {
98             // This can only be the case if we didn't have start_explicit, since required_by would
99             // otherwise by non-zero.
100             prop_release = !prop_require;
101             prop_require = false;
102             services->add_prop_queue(this);
103             services->service_inactive(this);
104         }
105     }
106
107     // Start failure will have been logged already, only log if we are stopped for other reasons:
108     if (! start_failed) {
109         log_service_stopped(service_name);
110
111         // If this service chains to another, start the other service now:
112         if (! will_restart && ! start_on_completion.empty()) {
113             try {
114                 auto chain_to = services->load_service(start_on_completion.c_str());
115                 chain_to->start();
116             }
117             catch (service_load_exc &sle) {
118                 log(loglevel_t::ERROR, "Couldn't chain to service ", start_on_completion, ": ",
119                         "couldn't load ", sle.service_name, ": ", sle.exc_description);
120             }
121             catch (std::bad_alloc &bae) {
122                 log(loglevel_t::ERROR, "Couldn't chain to service ", start_on_completion,
123                         ": Out of memory");
124             }
125         }
126     }
127     notify_listeners(service_event_t::STOPPED);
128 }
129
130 bool service_record::do_auto_restart() noexcept
131 {
132     if (auto_restart) {
133         return !services->is_shutting_down();
134     }
135     return false;
136 }
137
138 void service_record::require() noexcept
139 {
140     if (required_by++ == 0) {
141         prop_require = !prop_release;
142         prop_release = false;
143         services->add_prop_queue(this);
144         if (service_state != service_state_t::STARTING && service_state != service_state_t::STARTED) {
145             prop_start = true;
146         }
147     }
148 }
149
150 void service_record::release(bool issue_stop) noexcept
151 {
152     if (--required_by == 0) {
153         desired_state = service_state_t::STOPPED;
154
155         // Can stop, and can release dependencies now. We don't need to issue a release if
156         // the require was pending though:
157         prop_release = !prop_require;
158         prop_require = false;
159         services->add_prop_queue(this);
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     if (desired_state == service_state_t::STARTED && service_state != service_state_t::STOPPED) return;
192
193     bool was_active = service_state != service_state_t::STOPPED || desired_state != service_state_t::STOPPED;
194     desired_state = service_state_t::STARTED;
195     
196     if (service_state != service_state_t::STOPPED) {
197         // We're already starting/started, or we are stopping and need to wait for
198         // that the complete.
199         if (service_state != service_state_t::STOPPING || ! can_interrupt_stop()) {
200             return;
201         }
202         // We're STOPPING, and that can be interrupted. Our dependencies might be STOPPING,
203         // but if so they are waiting (for us), so they too can be instantly returned to
204         // STARTING state.
205         notify_listeners(service_event_t::STOPCANCELLED);
206     }
207     else if (! was_active) {
208         services->service_active(this);
209     }
210
211     start_failed = false;
212     start_skipped = false;
213     service_state = service_state_t::STARTING;
214     waiting_for_deps = true;
215
216     if (start_check_dependencies()) {
217         services->add_transition_queue(this);
218     }
219 }
220
221 void service_record::do_propagation() noexcept
222 {
223     if (prop_require) {
224         // Need to require all our dependencies
225         for (auto & dep : depends_on) {
226             dep.get_to()->require();
227             dep.holding_acq = true;
228         }
229         prop_require = false;
230     }
231     
232     if (prop_release) {
233         release_dependencies();
234         prop_release = false;
235     }
236     
237     if (prop_failure) {
238         prop_failure = false;
239         stop_reason = stopped_reason_t::DEPFAILED;
240         failed_to_start(true);
241     }
242     
243     if (prop_start) {
244         prop_start = false;
245         start(false);
246     }
247
248     if (prop_stop) {
249         prop_stop = false;
250         do_stop();
251     }
252 }
253
254 void service_record::execute_transition() noexcept
255 {
256     // state is STARTED with restarting set true if we are running a smooth recovery.
257     if (service_state == service_state_t::STARTING || (service_state == service_state_t::STARTED
258             && restarting)) {
259         if (check_deps_started()) {
260             all_deps_started();
261         }
262     }
263     else if (service_state == service_state_t::STOPPING) {
264         if (stop_check_dependents()) {
265             waiting_for_deps = false;
266             bring_down();
267         }
268     }
269 }
270
271 void service_record::do_start() noexcept
272 {
273     if (pinned_stopped) return;
274     
275     if (service_state != service_state_t::STARTING) {
276         return;
277     }
278     
279     service_state = service_state_t::STARTING;
280
281     waiting_for_deps = true;
282
283     // Ask dependencies to start, mark them as being waited on.
284     if (check_deps_started()) {
285         // Once all dependencies are started, we start properly:
286         all_deps_started();
287     }
288 }
289
290 void service_record::dependency_started() noexcept
291 {
292     // Note that we check for STARTED state here in case the service is in smooth recovery while pinned.
293     // In that case it will wait for dependencies to start before restarting the process.
294     if ((service_state == service_state_t::STARTING || service_state == service_state_t::STARTED)
295             && waiting_for_deps) {
296         services->add_transition_queue(this);
297     }
298 }
299
300 bool service_record::start_check_dependencies() noexcept
301 {
302     bool all_deps_started = true;
303
304     for (auto & dep : depends_on) {
305         service_record * to = dep.get_to();
306         if (to->service_state != service_state_t::STARTED) {
307             if (to->service_state != service_state_t::STARTING) {
308                 to->prop_start = true;
309                 services->add_prop_queue(to);
310             }
311             dep.waiting_on = true;
312             all_deps_started = false;
313         }
314     }
315     
316     return all_deps_started;
317 }
318
319 bool service_record::check_deps_started() noexcept
320 {
321     for (auto & dep : depends_on) {
322         if (dep.waiting_on) {
323             return false;
324         }
325     }
326
327     return true;
328 }
329
330 void service_record::all_deps_started() noexcept
331 {
332     if (onstart_flags.starts_on_console && ! have_console) {
333         queue_for_console();
334         return;
335     }
336     
337     waiting_for_deps = false;
338
339     if (! can_proceed_to_start()) {
340         waiting_for_deps = true;
341         return;
342     }
343
344     bool start_success = bring_up();
345     if (! start_success) {
346         failed_to_start();
347     }
348 }
349
350 void service_record::acquired_console() noexcept
351 {
352     waiting_for_console = false;
353     have_console = true;
354
355     if (service_state != service_state_t::STARTING) {
356         // We got the console but no longer want it.
357         release_console();
358     }
359     else if (check_deps_started()) {
360         all_deps_started();
361     }
362     else {
363         // We got the console but can't use it yet.
364         release_console();
365     }
366 }
367
368 void service_record::started() noexcept
369 {
370     // If we start on console but don't keep it, release it now:
371     if (have_console && ! onstart_flags.runs_on_console) {
372         bp_sys::tcsetpgrp(0, bp_sys::getpgrp());
373         release_console();
374     }
375
376     log_service_started(get_name());
377     service_state = service_state_t::STARTED;
378     notify_listeners(service_event_t::STARTED);
379
380     if (onstart_flags.rw_ready) {
381         rootfs_is_rw();
382     }
383     if (onstart_flags.log_ready) {
384         setup_external_log();
385     }
386
387     if (force_stop || desired_state == service_state_t::STOPPED) {
388         // We must now stop.
389         do_stop();
390         return;
391     }
392
393     // Notify any dependents whose desired state is STARTED:
394     for (auto dept : dependents) {
395         dept->get_from()->dependency_started();
396         dept->waiting_on = false;
397     }
398 }
399
400 void service_record::failed_to_start(bool depfailed, bool immediate_stop) noexcept
401 {
402     if (waiting_for_console) {
403         services->unqueue_console(this);
404         waiting_for_console = false;
405     }
406
407     if (start_explicit) {
408         start_explicit = false;
409         release(false);
410     }
411
412     // Cancel start of dependents:
413     for (auto & dept : dependents) {
414         switch (dept->dep_type) {
415         case dependency_type::REGULAR:
416         case dependency_type::MILESTONE:
417             if (dept->get_from()->service_state == service_state_t::STARTING) {
418                 dept->get_from()->prop_failure = true;
419                 services->add_prop_queue(dept->get_from());
420             }
421             break;
422         case dependency_type::WAITS_FOR:
423         case dependency_type::SOFT:
424             if (dept->waiting_on) {
425                 dept->waiting_on = false;
426                 dept->get_from()->dependency_started();
427             }
428         }
429
430         // Always release now, so that our desired state will be STOPPED before we call
431         // stopped() below (if we do so). Otherwise it may decide to restart us.
432         if (dept->holding_acq) {
433             dept->holding_acq = false;
434             release(false);
435         }
436     }
437
438     start_failed = true;
439     log_service_failed(get_name());
440     notify_listeners(service_event_t::FAILEDSTART);
441
442     if (immediate_stop) {
443         stopped();
444     }
445 }
446
447 bool service_record::bring_up() noexcept
448 {
449     // default implementation: there is no process, so we are started.
450     started();
451     return true;
452 }
453
454 // Mark this and all dependent services as force-stopped.
455 void service_record::forced_stop() noexcept
456 {
457     if (service_state != service_state_t::STOPPED) {
458         force_stop = true;
459         if (! pinned_started) {
460             prop_stop = true;
461             services->add_prop_queue(this);
462         }
463     }
464 }
465
466 void service_record::dependent_stopped() noexcept
467 {
468     if (service_state == service_state_t::STOPPING && waiting_for_deps) {
469         services->add_transition_queue(this);
470     }
471 }
472
473 void service_record::stop(bool bring_down) noexcept
474 {
475     if (start_explicit) {
476         start_explicit = false;
477         release();
478     }
479
480     if (bring_down && service_state != service_state_t::STOPPED
481                 && service_state != service_state_t::STOPPING) {
482         stop_reason = stopped_reason_t::NORMAL;
483         do_stop();
484     }
485 }
486
487 void service_record::do_stop() noexcept
488 {
489     // A service that does actually stop for any reason should have its explicit activation released, unless
490     // it will restart:
491     if (start_explicit && ! do_auto_restart()) {
492         start_explicit = false;
493         release(false);
494     }
495
496     bool all_deps_stopped = stop_dependents();
497
498     if (service_state != service_state_t::STARTED) {
499         if (service_state == service_state_t::STARTING) {
500             // If waiting for a dependency, or waiting for the console, we can interrupt start. Otherwise,
501             // we need to delegate to can_interrupt_start() (which can be overridden).
502             if (! waiting_for_deps && ! waiting_for_console) {
503                 if (! can_interrupt_start()) {
504                     // Well this is awkward: we're going to have to continue starting. We can stop once
505                     // we've reached the started state.
506                     return;
507                 }
508
509                 if (! interrupt_start()) {
510                     // Now wait for service startup to actually end; we don't need to handle it here.
511                     notify_listeners(service_event_t::STARTCANCELLED);
512                     return;
513                 }
514             }
515             else if (waiting_for_console) {
516                 services->unqueue_console(this);
517                 waiting_for_console = false;
518             }
519
520             // We must have had desired_state == STARTED.
521             notify_listeners(service_event_t::STARTCANCELLED);
522
523             // Reaching this point, we are starting interruptibly - so we
524             // stop now (by falling through to below).
525         }
526         else {
527             // If we're starting we need to wait for that to complete.
528             // If we're already stopping/stopped there's nothing to do.
529             return;
530         }
531     }
532
533     if (pinned_started) return;
534
535     service_state = service_state_t::STOPPING;
536     waiting_for_deps = true;
537     if (all_deps_stopped) {
538         services->add_transition_queue(this);
539     }
540 }
541
542 bool service_record::stop_check_dependents() noexcept
543 {
544     bool all_deps_stopped = true;
545     for (auto dept : dependents) {
546         if (dept->dep_type == dependency_type::REGULAR && ! dept->get_from()->is_stopped()) {
547             all_deps_stopped = false;
548             break;
549         }
550     }
551     
552     return all_deps_stopped;
553 }
554
555 bool service_record::stop_dependents() noexcept
556 {
557     bool all_deps_stopped = true;
558     for (auto dept : dependents) {
559         if (dept->dep_type == dependency_type::REGULAR ||
560                 (dept->dep_type == dependency_type::MILESTONE &&
561                 dept->get_from()->service_state != service_state_t::STARTED)) {
562             if (! dept->get_from()->is_stopped()) {
563                 // Note we check *first* since if the dependent service is not stopped,
564                 // 1. We will issue a stop to it shortly and
565                 // 2. It will notify us when stopped, at which point the stop_check_dependents()
566                 //    check is run anyway.
567                 all_deps_stopped = false;
568             }
569
570             if (force_stop) {
571                 // If this service is to be forcefully stopped, dependents must also be.
572                 dept->get_from()->forced_stop();
573             }
574
575             dept->get_from()->prop_stop = true;
576             services->add_prop_queue(dept->get_from());
577         }
578         else {
579             // waits-for or soft dependency:
580             if (dept->waiting_on) {
581                 dept->waiting_on = false;
582                 dept->get_from()->dependency_started();
583             }
584             if (dept->holding_acq) {
585                 dept->holding_acq = false;
586                 // release without issuing stop, since we should be called only when this
587                 // service is already stopped/stopping:
588                 release(false);
589             }
590         }
591     }
592
593     return all_deps_stopped;
594 }
595
596 // All dependents have stopped; we can stop now, too. Only called when STOPPING.
597 void service_record::bring_down() noexcept
598 {
599     waiting_for_deps = false;
600     stopped();
601 }
602
603 void service_record::unpin() noexcept
604 {
605     if (pinned_started) {
606         pinned_started = false;
607         if (desired_state == service_state_t::STOPPED || force_stop) {
608             do_stop();
609             services->process_queues();
610         }
611     }
612     if (pinned_stopped) {
613         pinned_stopped = false;
614         if (desired_state == service_state_t::STARTED) {
615             do_start();
616             services->process_queues();
617         }
618     }
619 }
620
621 void service_record::queue_for_console() noexcept
622 {
623     waiting_for_console = true;
624     services->append_console_queue(this);
625 }
626
627 void service_record::release_console() noexcept
628 {
629     have_console = false;
630     services->pull_console_queue();
631 }
632
633 bool service_record::interrupt_start() noexcept
634 {
635     return true;
636 }
637
638 void service_set::service_active(service_record *sr) noexcept
639 {
640     active_services++;
641 }
642
643 void service_set::service_inactive(service_record *sr) noexcept
644 {
645     active_services--;
646 }