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