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