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