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