Adjust dependency auto-break logic.
[oweals/dinit.git] / src / proc-service.cc
1 #include <sys/un.h>
2 #include <sys/socket.h>
3
4 #include "dinit.h"
5 #include "dinit-socket.h"
6 #include "dinit-util.h"
7 #include "dinit-log.h"
8 #include "proc-service.h"
9
10 /*
11  * Most of the implementation for process-based services (process, scripted, bgprocess) is here.
12  *
13  * See proc-service.h header for interface details.
14  */
15
16 // Given a string and a list of pairs of (start,end) indices for each argument in that string,
17 // store a null terminator for the argument. Return a `char *` vector containing the beginning
18 // of each argument and a trailing nullptr. (The returned array is invalidated if the string is later modified).
19 std::vector<const char *> separate_args(std::string &s,
20         const std::list<std::pair<unsigned,unsigned>> &arg_indices)
21 {
22     std::vector<const char *> r;
23     r.reserve(arg_indices.size() + 1);
24
25     // First store nul terminator for each part:
26     for (auto index_pair : arg_indices) {
27         if (index_pair.second < s.length()) {
28             s[index_pair.second] = 0;
29         }
30     }
31
32     // Now we can get the C string (c_str) and store offsets into it:
33     const char * cstr = s.c_str();
34     for (auto index_pair : arg_indices) {
35         r.push_back(cstr + index_pair.first);
36     }
37     r.push_back(nullptr);
38     return r;
39 }
40
41 void process_service::exec_succeeded() noexcept
42 {
43     // This could be a smooth recovery (state already STARTED). Even more, the process
44     // might be stopped (and killed via a signal) during smooth recovery.  We don't to
45     // process startup again in either case, so we check for state STARTING:
46     if (get_state() == service_state_t::STARTING) {
47         started();
48     }
49     else if (get_state() == service_state_t::STOPPING) {
50         // stopping, but smooth recovery was in process. That's now over so we can
51         // commence normal stop. Note that if pid == -1 the process already stopped(!),
52         // that's handled below.
53         if (pid != -1 && stop_check_dependents()) {
54             bring_down();
55         }
56     }
57 }
58
59 void scripted_service::exec_succeeded() noexcept
60 {
61         // For a scripted service, this means nothing other than that the start/stop
62         // script will now begin.
63 }
64
65 rearm exec_status_pipe_watcher::fd_event(eventloop_t &loop, int fd, int flags) noexcept
66 {
67     base_process_service *sr = service;
68     sr->waiting_for_execstat = false;
69
70     int exec_status;
71     int r = read(get_watched_fd(), &exec_status, sizeof(int));
72     deregister(loop);
73     close(get_watched_fd());
74
75     if (r > 0) {
76         // We read an errno code; exec() failed, and the service startup failed.
77         if (sr->pid != -1) {
78             sr->child_listener.deregister(event_loop, sr->pid);
79             sr->reserved_child_watch = false;
80             if (sr->stop_timer_armed) {
81                 sr->restart_timer.stop_timer(loop);
82                 sr->stop_timer_armed = false;
83             }
84         }
85         sr->pid = -1;
86         sr->exec_failed(exec_status);
87     }
88     else {
89         sr->exec_succeeded();
90
91         if (sr->pid == -1) {
92             // Somehow the process managed to complete before we even saw the exec() status.
93             sr->handle_exit_status(sr->exit_status);
94         }
95     }
96
97     sr->services->process_queues();
98
99     return rearm::REMOVED;
100 }
101
102 dasynq::rearm service_child_watcher::status_change(eventloop_t &loop, pid_t child, int status) noexcept
103 {
104     base_process_service *sr = service;
105
106     sr->pid = -1;
107     sr->exit_status = bp_sys::exit_status(status);
108
109     // Ok, for a process service, any process death which we didn't rig
110     // ourselves is a bit... unexpected. Probably, the child died because
111     // we asked it to (sr->service_state == STOPPING). But even if
112     // we didn't, there's not much we can do.
113
114     if (sr->waiting_for_execstat) {
115         // We still don't have an exec() status from the forked child, wait for that
116         // before doing any further processing.
117         return dasynq::rearm::NOOP; // hold watch reservation
118     }
119
120     // Must stop watch now since handle_exit_status might result in re-launch:
121     // (stop_watch instead of deregister, so that we hold watch reservation).
122     stop_watch(loop);
123
124     if (sr->stop_timer_armed) {
125         sr->restart_timer.stop_timer(loop);
126         sr->stop_timer_armed = false;
127     }
128
129     sr->handle_exit_status(bp_sys::exit_status(status));
130     return dasynq::rearm::NOOP;
131 }
132
133 void process_service::handle_exit_status(bp_sys::exit_status exit_status) noexcept
134 {
135     bool did_exit = exit_status.did_exit();
136     bool was_signalled = exit_status.was_signalled();
137     restarting = false;
138     auto service_state = get_state();
139
140     if (exit_status.did_exit_clean() && service_state != service_state_t::STOPPING) {
141         if (did_exit) {
142             log(loglevel_t::ERROR, "Service ", get_name(), " process terminated with exit code ",
143                     exit_status.get_exit_status());
144         }
145         else if (was_signalled) {
146             log(loglevel_t::ERROR, "Service ", get_name(), " terminated due to signal ",
147                     exit_status.get_term_sig());
148         }
149     }
150
151     if (service_state == service_state_t::STARTING) {
152         if (exit_status.did_exit_clean()) {
153             started();
154         }
155         else {
156             stop_reason = stopped_reason_t::FAILED;
157             failed_to_start();
158         }
159     }
160     else if (service_state == service_state_t::STOPPING) {
161         // We won't log a non-zero exit status or termination due to signal here -
162         // we assume that the process died because we signalled it.
163         if (stop_timer_armed) {
164             restart_timer.stop_timer(event_loop);
165         }
166         stopped();
167     }
168     else if (smooth_recovery && service_state == service_state_t::STARTED
169             && get_target_state() == service_state_t::STARTED) {
170         do_smooth_recovery();
171         return;
172     }
173     else {
174         stop_reason = stopped_reason_t::TERMINATED;
175         emergency_stop();
176     }
177     services->process_queues();
178 }
179
180 void process_service::exec_failed(int errcode) noexcept
181 {
182     log(loglevel_t::ERROR, get_name(), ": execution failed: ", strerror(errcode));
183     if (get_state() == service_state_t::STARTING) {
184         stop_reason = stopped_reason_t::EXECFAILED;
185         failed_to_start();
186     }
187     else {
188         // Process service in smooth recovery:
189         stop_reason = stopped_reason_t::TERMINATED;
190         emergency_stop();
191     }
192 }
193
194 void bgproc_service::handle_exit_status(bp_sys::exit_status exit_status) noexcept
195 {
196     begin:
197     bool did_exit = exit_status.did_exit();
198     bool was_signalled = exit_status.was_signalled();
199     auto service_state = get_state();
200
201     if (!exit_status.did_exit_clean() && service_state != service_state_t::STOPPING) {
202         if (did_exit) {
203             log(loglevel_t::ERROR, "Service ", get_name(), " process terminated with exit code ",
204                     exit_status.get_exit_status());
205         }
206         else if (was_signalled) {
207             log(loglevel_t::ERROR, "Service ", get_name(), " terminated due to signal ",
208                     exit_status.get_term_sig());
209         }
210     }
211
212     // This may be a "smooth recovery" where we are restarting the process while leaving the
213     // service in the STARTED state.
214     if (restarting && service_state == service_state_t::STARTED) {
215         restarting = false;
216         bool need_stop = false;
217         if ((did_exit && exit_status.get_exit_status() != 0) || was_signalled) {
218             need_stop = true;
219         }
220         else {
221             // We need to re-read the PID, since it has now changed.
222             if (pid_file.length() != 0) {
223                 auto pid_result = read_pid_file(&exit_status);
224                 switch (pid_result) {
225                     case pid_result_t::FAILED:
226                         // Failed startup: no auto-restart.
227                         need_stop = true;
228                         break;
229                     case pid_result_t::TERMINATED:
230                         goto begin;
231                     case pid_result_t::OK:
232                         break;
233                 }
234             }
235         }
236
237         if (need_stop) {
238             // Failed startup: no auto-restart.
239             stop_reason = stopped_reason_t::TERMINATED;
240             emergency_stop();
241             services->process_queues();
242         }
243
244         return;
245     }
246
247     restarting = false;
248     if (service_state == service_state_t::STARTING) {
249         // POSIX requires that if the process exited clearly with a status code of 0,
250         // the exit status value will be 0:
251         if (exit_status.did_exit_clean()) {
252             auto pid_result = read_pid_file(&exit_status);
253             switch (pid_result) {
254                 case pid_result_t::FAILED:
255                     // Failed startup: no auto-restart.
256                     stop_reason = stopped_reason_t::FAILED;
257                     failed_to_start();
258                     break;
259                 case pid_result_t::TERMINATED:
260                     // started, but immediately terminated
261                     started();
262                     goto begin;
263                 case pid_result_t::OK:
264                     started();
265                     break;
266             }
267         }
268         else {
269             stop_reason = stopped_reason_t::FAILED;
270             failed_to_start();
271         }
272     }
273     else if (service_state == service_state_t::STOPPING) {
274         // We won't log a non-zero exit status or termination due to signal here -
275         // we assume that the process died because we signalled it.
276         stopped();
277     }
278     else {
279         // we must be STARTED
280         if (smooth_recovery && get_target_state() == service_state_t::STARTED) {
281             do_smooth_recovery();
282             return;
283         }
284         if (! do_auto_restart() && start_explicit) {
285             start_explicit = false;
286             release(false);
287         }
288         stop_reason = stopped_reason_t::TERMINATED;
289         forced_stop();
290         stop_dependents();
291         stopped();
292     }
293     services->process_queues();
294 }
295
296 void bgproc_service::exec_failed(int errcode) noexcept
297 {
298     log(loglevel_t::ERROR, get_name(), ": execution failed: ", strerror(errcode));
299     // Only time we execute is for startup:
300     stop_reason = stopped_reason_t::EXECFAILED;
301     failed_to_start();
302 }
303
304 void scripted_service::handle_exit_status(bp_sys::exit_status exit_status) noexcept
305 {
306     bool did_exit = exit_status.did_exit();
307     bool was_signalled = exit_status.was_signalled();
308     auto service_state = get_state();
309
310     // For a scripted service, a termination occurs in one of three main cases:
311     // - the start script completed (or failed), when service was STARTING
312     // - the start script was interrupted to cancel startup; state is STOPPING
313     // - the stop script complete (or failed), state is STOPPING
314
315     if (service_state == service_state_t::STOPPING) {
316         // We might be running the stop script, or we might be running the start script and have issued
317         // a cancel order via SIGINT:
318         if (interrupting_start) {
319             // We issued a start interrupt, so we expected this failure:
320             if (did_exit && exit_status.get_exit_status() != 0) {
321                 log(loglevel_t::INFO, "Service ", get_name(), " start cancelled; exit code ",
322                         exit_status.get_exit_status());
323                 // Assume that a command terminating normally requires no cleanup:
324                 stopped();
325             }
326             else {
327                 if (was_signalled) {
328                     log(loglevel_t::INFO, "Service ", get_name(), " start cancelled from signal ",
329                             exit_status.get_term_sig());
330                 }
331                 // If the start script completed successfully, or was interrupted via our signal,
332                 // we want to run the stop script to clean up:
333                 bring_down();
334             }
335             interrupting_start = false;
336         }
337         else if (exit_status.did_exit_clean()) {
338             // We were running the stop script and finished successfully
339             stopped();
340         }
341         else {
342             // ??? failed to stop! Let's log it as warning:
343             if (did_exit) {
344                 log(loglevel_t::WARN, "Service ", get_name(), " stop command failed with exit code ",
345                         exit_status.get_exit_status());
346             }
347             else if (was_signalled) {
348                 log(loglevel_t::WARN, "Service ", get_name(), " stop command terminated due to signal ",
349                         exit_status.get_term_sig());
350             }
351             // Even if the stop script failed, assume that service is now stopped, so that any dependencies
352             // can be stopped. There's not really any other useful course of action here.
353             stopped();
354         }
355         services->process_queues();
356     }
357     else { // STARTING
358         if (exit_status.did_exit_clean()) {
359             started();
360         }
361         else if (was_signalled && exit_status.get_term_sig() == SIGINT && onstart_flags.skippable) {
362             // A skippable service can be skipped by interrupting (eg by ^C if the service
363             // starts on the console).
364             start_skipped = true;
365             started();
366         }
367         else {
368             // failed to start
369             if (did_exit) {
370                 log(loglevel_t::ERROR, "Service ", get_name(), " command failed with exit code ",
371                         exit_status.get_exit_status());
372             }
373             else if (was_signalled) {
374                 log(loglevel_t::ERROR, "Service ", get_name(), " command terminated due to signal ",
375                         exit_status.get_term_sig());
376             }
377             stop_reason = stopped_reason_t::FAILED;
378             failed_to_start();
379         }
380         services->process_queues();
381     }
382 }
383
384 void scripted_service::exec_failed(int errcode) noexcept
385 {
386     log(loglevel_t::ERROR, get_name(), ": execution failed: ", strerror(errcode));
387     auto service_state = get_state();
388     if (service_state == service_state_t::STARTING) {
389         stop_reason = stopped_reason_t::EXECFAILED;
390         failed_to_start();
391     }
392     else if (service_state == service_state_t::STOPPING) {
393         // We've logged the failure, but it's probably better not to leave the service in
394         // STOPPING state:
395         stopped();
396     }
397 }
398
399 bgproc_service::pid_result_t
400 bgproc_service::read_pid_file(bp_sys::exit_status *exit_status) noexcept
401 {
402     const char *pid_file_c = pid_file.c_str();
403     int fd = open(pid_file_c, O_CLOEXEC);
404     if (fd == -1) {
405         log(loglevel_t::ERROR, get_name(), ": read pid file: ", strerror(errno));
406         return pid_result_t::FAILED;
407     }
408
409     char pidbuf[21]; // just enough to hold any 64-bit integer
410     int r = ss_read(fd, pidbuf, 20);
411     if (r < 0) {
412         // Could not read from PID file
413         log(loglevel_t::ERROR, get_name(), ": could not read from pidfile; ", strerror(errno));
414         close(fd);
415         return pid_result_t::FAILED;
416     }
417
418     close(fd);
419     pidbuf[r] = 0; // store nul terminator
420
421     bool valid_pid = false;
422     try {
423         unsigned long long v = std::stoull(pidbuf, nullptr, 0);
424         if (v <= std::numeric_limits<pid_t>::max()) {
425             pid = (pid_t) v;
426             valid_pid = true;
427         }
428     }
429     catch (std::out_of_range &exc) {
430         // Too large?
431     }
432     catch (std::invalid_argument &exc) {
433         // Ok, so it doesn't look like a number: proceed...
434     }
435
436     if (valid_pid) {
437         pid_t wait_r = waitpid(pid, exit_status, WNOHANG);
438         if (wait_r == -1 && errno == ECHILD) {
439             // We can't track this child - check process exists:
440             if (kill(pid, 0) == 0 || errno != ESRCH) {
441                 tracking_child = false;
442                 return pid_result_t::OK;
443             }
444             else {
445                 log(loglevel_t::ERROR, get_name(), ": pid read from pidfile (", pid, ") is not valid");
446                 pid = -1;
447                 return pid_result_t::FAILED;
448             }
449         }
450         else if (wait_r == pid) {
451             pid = -1;
452             return pid_result_t::TERMINATED;
453         }
454         else if (wait_r == 0) {
455             // We can track the child
456             child_listener.add_reserved(event_loop, pid, dasynq::DEFAULT_PRIORITY - 10);
457             tracking_child = true;
458             reserved_child_watch = true;
459             return pid_result_t::OK;
460         }
461     }
462
463     log(loglevel_t::ERROR, get_name(), ": pid read from pidfile (", pid, ") is not valid");
464     pid = -1;
465     return pid_result_t::FAILED;
466 }
467
468 void process_service::bring_down() noexcept
469 {
470     if (waiting_for_execstat) {
471         // The process is still starting. This should be uncommon, but can occur during
472         // smooth recovery. We can't do much now; we have to wait until we get the
473         // status, and then act appropriately.
474         return;
475     }
476     else if (pid != -1) {
477         // The process is still kicking on - must actually kill it. We signal the process
478         // group (-pid) rather than just the process as there's less risk then of creating
479         // an orphaned process group:
480         if (! onstart_flags.no_sigterm) {
481             kill_pg(SIGTERM);
482         }
483         if (term_signal != -1) {
484             kill_pg(term_signal);
485         }
486
487         // If there's a stop timeout, arm the timer now:
488         if (stop_timeout != time_val(0,0)) {
489             restart_timer.arm_timer_rel(event_loop, stop_timeout);
490             stop_timer_armed = true;
491         }
492
493         // The rest is done in handle_exit_status.
494     }
495     else {
496         // The process is already dead.
497         stopped();
498     }
499 }
500
501 void bgproc_service::bring_down() noexcept
502 {
503     if (pid != -1) {
504         // The process is still kicking on - must actually kill it. We signal the process
505         // group (-pid) rather than just the process as there's less risk then of creating
506         // an orphaned process group:
507         if (! onstart_flags.no_sigterm) {
508             kill_pg(SIGTERM);
509         }
510         if (term_signal != -1) {
511             kill_pg(term_signal);
512         }
513
514         // In most cases, the rest is done in handle_exit_status.
515         // If we are a BGPROCESS and the process is not our immediate child, however, that
516         // won't work - check for this now:
517         if (! tracking_child) {
518             stopped();
519         }
520         else if (stop_timeout != time_val(0,0)) {
521             restart_timer.arm_timer_rel(event_loop, stop_timeout);
522             stop_timer_armed = true;
523         }
524     }
525     else {
526         // The process is already dead.
527         stopped();
528     }
529 }
530
531 void scripted_service::bring_down() noexcept
532 {
533         if (pid != -1) {
534                 // We're already running the stop script; nothing to do.
535                 return;
536         }
537
538     if (stop_command.length() == 0) {
539         stopped();
540     }
541     else if (! start_ps_process(stop_arg_parts, false)) {
542         // Couldn't execute stop script, but there's not much we can do:
543         stopped();
544     }
545     else {
546         // successfully started stop script: start kill timer:
547         if (stop_timeout != time_val(0,0)) {
548             restart_timer.arm_timer_rel(event_loop, stop_timeout);
549             stop_timer_armed = true;
550         }
551     }
552 }
553
554 dasynq::rearm process_restart_timer::timer_expiry(eventloop_t &, int expiry_count)
555 {
556     service->timer_expired();
557
558     // Leave the timer disabled, or, if it has been reset by any processing above, leave it armed:
559     return dasynq::rearm::NOOP;
560 }