]>
Commit | Line | Data |
---|---|---|
5cb5a6ff LP |
1 | /*-*- Mode: C; c-basic-offset: 8 -*-*/ |
2 | ||
3 | #include <errno.h> | |
034c6ed7 | 4 | #include <signal.h> |
5cb5a6ff LP |
5 | |
6 | #include "name.h" | |
7 | #include "service.h" | |
8 | #include "load-fragment.h" | |
9 | #include "load-dropin.h" | |
034c6ed7 LP |
10 | #include "log.h" |
11 | ||
12 | static const NameActiveState state_table[_SERVICE_STATE_MAX] = { | |
13 | [SERVICE_DEAD] = NAME_INACTIVE, | |
14 | [SERVICE_START_PRE] = NAME_ACTIVATING, | |
15 | [SERVICE_START] = NAME_ACTIVATING, | |
16 | [SERVICE_START_POST] = NAME_ACTIVATING, | |
17 | [SERVICE_RUNNING] = NAME_ACTIVE, | |
18 | [SERVICE_RELOAD] = NAME_ACTIVE_RELOADING, | |
19 | [SERVICE_STOP] = NAME_DEACTIVATING, | |
20 | [SERVICE_STOP_SIGTERM] = NAME_DEACTIVATING, | |
21 | [SERVICE_STOP_SIGKILL] = NAME_DEACTIVATING, | |
22 | [SERVICE_STOP_POST] = NAME_DEACTIVATING, | |
23 | [SERVICE_FINAL_SIGTERM] = NAME_DEACTIVATING, | |
24 | [SERVICE_FINAL_SIGKILL] = NAME_DEACTIVATING, | |
25 | [SERVICE_MAINTAINANCE] = NAME_INACTIVE, | |
26 | [SERVICE_AUTO_RESTART] = NAME_ACTIVATING, | |
27 | }; | |
5cb5a6ff LP |
28 | |
29 | static int service_load_sysv(Service *s) { | |
30 | assert(s); | |
31 | ||
32 | /* Load service data from SysV init scripts, preferably with | |
33 | * LSB headers ... */ | |
34 | ||
35 | return -ENOENT; | |
36 | } | |
37 | ||
034c6ed7 | 38 | static int service_init(Name *n) { |
5cb5a6ff LP |
39 | int r; |
40 | Service *s = SERVICE(n); | |
41 | ||
42 | assert(s); | |
43 | ||
034c6ed7 LP |
44 | /* First, reset everything to the defaults, in case this is a |
45 | * reload */ | |
46 | ||
47 | s->type = 0; | |
48 | s->restart = 0; | |
49 | ||
50 | s->timeout_usec = DEFAULT_TIMEOUT_USEC; | |
51 | s->restart_usec = DEFAULT_RESTART_USEC; | |
52 | ||
53 | exec_context_init(&s->exec_context); | |
54 | ||
55 | s->timer_id = -1; | |
56 | ||
57 | s->state = SERVICE_DEAD; | |
5cb5a6ff LP |
58 | |
59 | /* Load a .service file */ | |
60 | r = name_load_fragment(n); | |
61 | ||
62 | /* Load a classic init script as a fallback */ | |
63 | if (r == -ENOENT) | |
64 | r = service_load_sysv(s); | |
65 | ||
66 | if (r < 0) | |
67 | return r; | |
68 | ||
69 | /* Load dropin directory data */ | |
70 | if ((r = name_load_dropin(n)) < 0) | |
71 | return r; | |
72 | ||
73 | return 0; | |
74 | } | |
75 | ||
034c6ed7 LP |
76 | static void service_done(Name *n) { |
77 | Service *s = SERVICE(n); | |
78 | ||
79 | assert(s); | |
80 | ||
81 | free(s->pid_file); | |
82 | s->pid_file = NULL; | |
83 | ||
84 | exec_context_done(&s->exec_context); | |
85 | exec_command_free_array(s->exec_command, _SERVICE_EXEC_MAX); | |
86 | s->control_command = NULL; | |
87 | ||
88 | /* This will leak a process, but at least no memory or any of | |
89 | * our resources */ | |
90 | if (s->main_pid > 0) { | |
91 | name_unwatch_pid(n, s->main_pid); | |
92 | s->main_pid = 0; | |
93 | } | |
94 | ||
95 | if (s->control_pid > 0) { | |
96 | name_unwatch_pid(n, s->control_pid); | |
97 | s->control_pid = 0; | |
98 | } | |
99 | ||
100 | name_unwatch_timer(n, &s->timer_id); | |
101 | } | |
102 | ||
5cb5a6ff LP |
103 | static void service_dump(Name *n, FILE *f, const char *prefix) { |
104 | ||
105 | static const char* const state_table[_SERVICE_STATE_MAX] = { | |
106 | [SERVICE_DEAD] = "dead", | |
107 | [SERVICE_START_PRE] = "start-pre", | |
108 | [SERVICE_START] = "start", | |
109 | [SERVICE_START_POST] = "post", | |
110 | [SERVICE_RUNNING] = "running", | |
5cb5a6ff | 111 | [SERVICE_RELOAD] = "reload", |
5cb5a6ff | 112 | [SERVICE_STOP] = "stop", |
034c6ed7 LP |
113 | [SERVICE_STOP_SIGTERM] = "stop-sigterm", |
114 | [SERVICE_STOP_SIGKILL] = "stop-sigkill", | |
5cb5a6ff | 115 | [SERVICE_STOP_POST] = "stop-post", |
034c6ed7 LP |
116 | [SERVICE_FINAL_SIGTERM] = "final-sigterm", |
117 | [SERVICE_FINAL_SIGKILL] = "final-sigkill", | |
118 | [SERVICE_MAINTAINANCE] = "maintainance", | |
119 | [SERVICE_AUTO_RESTART] = "auto-restart", | |
5cb5a6ff LP |
120 | }; |
121 | ||
122 | static const char* const command_table[_SERVICE_EXEC_MAX] = { | |
034c6ed7 LP |
123 | [SERVICE_EXEC_START_PRE] = "ExecStartPre", |
124 | [SERVICE_EXEC_START] = "ExecStart", | |
125 | [SERVICE_EXEC_START_POST] = "ExecStartPost", | |
126 | [SERVICE_EXEC_RELOAD] = "ExecReload", | |
127 | [SERVICE_EXEC_STOP] = "ExecStop", | |
128 | [SERVICE_EXEC_STOP_POST] = "ExecStopPost", | |
5cb5a6ff LP |
129 | }; |
130 | ||
131 | ServiceExecCommand c; | |
132 | Service *s = SERVICE(n); | |
133 | ||
134 | assert(s); | |
135 | ||
136 | fprintf(f, | |
137 | "%sService State: %s\n", | |
138 | prefix, state_table[s->state]); | |
139 | ||
034c6ed7 LP |
140 | if (s->pid_file) |
141 | fprintf(f, | |
142 | "%sPIDFile: %s\n", | |
143 | prefix, s->pid_file); | |
144 | ||
145 | ||
5cb5a6ff LP |
146 | exec_context_dump(&s->exec_context, f, prefix); |
147 | ||
148 | for (c = 0; c < _SERVICE_EXEC_MAX; c++) { | |
149 | ExecCommand *i; | |
150 | ||
034c6ed7 | 151 | LIST_FOREACH(command, i, s->exec_command[c]) |
5cb5a6ff LP |
152 | fprintf(f, "%s%s: %s\n", prefix, command_table[c], i->path); |
153 | } | |
154 | } | |
155 | ||
034c6ed7 LP |
156 | static int service_load_pid_file(Service *s) { |
157 | char *k; | |
158 | unsigned long p; | |
159 | int r; | |
160 | ||
161 | assert(s); | |
162 | ||
163 | if (s->main_pid_known) | |
164 | return 0; | |
165 | ||
166 | if (!s->pid_file) | |
167 | return -ENOENT; | |
168 | ||
169 | if ((r = read_one_line_file(s->pid_file, &k)) < 0) | |
170 | return r; | |
171 | ||
172 | if ((r = safe_atolu(k, &p)) < 0) { | |
173 | free(k); | |
174 | return r; | |
175 | } | |
176 | ||
177 | if ((unsigned long) (pid_t) p != p) | |
178 | return -ERANGE; | |
179 | ||
180 | s->main_pid = p; | |
181 | s->main_pid_known = true; | |
182 | ||
183 | return 0; | |
184 | } | |
185 | ||
186 | static void service_set_state(Service *s, ServiceState state) { | |
187 | ServiceState old_state; | |
5cb5a6ff LP |
188 | assert(s); |
189 | ||
034c6ed7 | 190 | old_state = s->state; |
5cb5a6ff | 191 | s->state = state; |
034c6ed7 LP |
192 | |
193 | if (state != SERVICE_START_PRE && | |
194 | state != SERVICE_START && | |
195 | state != SERVICE_START_POST && | |
196 | state != SERVICE_RELOAD && | |
197 | state != SERVICE_STOP && | |
198 | state != SERVICE_STOP_SIGTERM && | |
199 | state != SERVICE_STOP_SIGKILL && | |
200 | state != SERVICE_STOP_POST && | |
201 | state != SERVICE_FINAL_SIGTERM && | |
202 | state != SERVICE_FINAL_SIGKILL && | |
203 | state != SERVICE_AUTO_RESTART) | |
204 | name_unwatch_timer(NAME(s), &s->timer_id); | |
205 | ||
206 | if (state != SERVICE_START_POST && | |
207 | state != SERVICE_RUNNING && | |
208 | state != SERVICE_RELOAD && | |
209 | state != SERVICE_STOP && | |
210 | state != SERVICE_STOP_SIGTERM && | |
211 | state != SERVICE_STOP_SIGKILL) | |
212 | if (s->main_pid >= 0) { | |
213 | name_unwatch_pid(NAME(s), s->main_pid); | |
214 | s->main_pid = 0; | |
215 | } | |
216 | ||
217 | if (state != SERVICE_START_PRE && | |
218 | state != SERVICE_START && | |
219 | state != SERVICE_START_POST && | |
220 | state != SERVICE_RELOAD && | |
221 | state != SERVICE_STOP && | |
222 | state != SERVICE_STOP_SIGTERM && | |
223 | state != SERVICE_STOP_SIGKILL && | |
224 | state != SERVICE_STOP_POST && | |
225 | state != SERVICE_FINAL_SIGTERM && | |
226 | state != SERVICE_FINAL_SIGKILL) | |
227 | if (s->control_pid >= 0) { | |
228 | name_unwatch_pid(NAME(s), s->control_pid); | |
229 | s->control_pid = 0; | |
230 | } | |
231 | ||
232 | if (state != SERVICE_START_PRE && | |
233 | state != SERVICE_START && | |
234 | state != SERVICE_START_POST && | |
235 | state != SERVICE_RELOAD && | |
236 | state != SERVICE_STOP && | |
237 | state != SERVICE_STOP_POST) | |
238 | s->control_command = NULL; | |
239 | ||
240 | name_notify(NAME(s), state_table[old_state], state_table[s->state]); | |
241 | } | |
242 | ||
243 | static int service_spawn(Service *s, ExecCommand *c, bool timeout, pid_t *_pid) { | |
244 | pid_t pid; | |
245 | int r; | |
246 | ||
247 | assert(s); | |
248 | assert(c); | |
249 | assert(_pid); | |
250 | ||
251 | if (timeout) { | |
252 | if ((r = name_watch_timer(NAME(s), s->timeout_usec, &s->timer_id)) < 0) | |
253 | goto fail; | |
254 | } else | |
255 | name_unwatch_timer(NAME(s), &s->timer_id); | |
256 | ||
257 | if ((r = exec_spawn(c, &s->exec_context, NULL, 0, &pid)) < 0) | |
258 | goto fail; | |
259 | ||
260 | if ((r = name_watch_pid(NAME(s), pid)) < 0) | |
261 | /* FIXME: we need to do something here */ | |
262 | goto fail; | |
263 | ||
264 | *_pid = pid; | |
265 | ||
5cb5a6ff | 266 | return 0; |
034c6ed7 LP |
267 | |
268 | fail: | |
269 | if (timeout) | |
270 | name_unwatch_timer(NAME(s), &s->timer_id); | |
271 | ||
272 | return r; | |
273 | } | |
274 | ||
275 | static void service_enter_dead(Service *s, bool success, bool allow_restart) { | |
276 | int r; | |
277 | assert(s); | |
278 | ||
279 | if (!success) | |
280 | s->failure = true; | |
281 | ||
282 | if (allow_restart && | |
283 | (s->restart == SERVICE_RESTART_ALWAYS || | |
284 | (s->restart == SERVICE_RESTART_ON_SUCCESS && !s->failure))) { | |
285 | ||
286 | if ((r = name_watch_timer(NAME(s), s->restart_usec, &s->timer_id)) < 0) | |
287 | goto fail; | |
288 | ||
289 | service_set_state(s, SERVICE_AUTO_RESTART); | |
290 | } else | |
291 | service_set_state(s, s->failure ? SERVICE_MAINTAINANCE : SERVICE_DEAD); | |
292 | ||
293 | return; | |
294 | ||
295 | fail: | |
296 | log_warning("%s failed to run install restart timer: %s", name_id(NAME(s)), strerror(-r)); | |
297 | service_enter_dead(s, false, false); | |
298 | } | |
299 | ||
300 | static void service_enter_signal(Service *s, ServiceState state, bool success); | |
301 | ||
302 | static void service_enter_stop_post(Service *s, bool success) { | |
303 | int r; | |
304 | assert(s); | |
305 | ||
306 | if (!success) | |
307 | s->failure = true; | |
308 | ||
309 | if ((s->control_command = s->exec_command[SERVICE_EXEC_STOP_POST])) { | |
310 | ||
311 | if ((r = service_spawn(s, s->control_command, true, &s->control_pid)) < 0) | |
312 | goto fail; | |
313 | ||
314 | service_set_state(s, SERVICE_STOP_POST); | |
315 | } else | |
316 | service_enter_dead(s, true, true); | |
317 | ||
318 | return; | |
319 | ||
320 | fail: | |
321 | log_warning("%s failed to run stop executable: %s", name_id(NAME(s)), strerror(-r)); | |
322 | service_enter_signal(s, SERVICE_FINAL_SIGTERM, false); | |
323 | } | |
324 | ||
325 | static void service_enter_signal(Service *s, ServiceState state, bool success) { | |
326 | int r; | |
327 | bool sent = false; | |
328 | ||
329 | assert(s); | |
330 | ||
331 | if (!success) | |
332 | s->failure = true; | |
333 | ||
334 | if (s->main_pid > 0 || s->control_pid > 0) { | |
335 | int sig; | |
336 | ||
337 | sig = (state == SERVICE_STOP_SIGTERM || state == SERVICE_FINAL_SIGTERM) ? SIGTERM : SIGKILL; | |
338 | ||
339 | r = 0; | |
340 | if (s->main_pid > 0) { | |
341 | if (kill(s->main_pid, sig) < 0 && errno != ESRCH) | |
342 | r = -errno; | |
343 | else | |
344 | sent = true; | |
345 | } | |
346 | ||
347 | if (s->control_pid > 0) { | |
348 | if (kill(s->control_pid, sig) < 0 && errno != ESRCH) | |
349 | r = -errno; | |
350 | else | |
351 | sent = true; | |
352 | } | |
353 | ||
354 | if (r < 0) | |
355 | goto fail; | |
356 | ||
357 | service_set_state(s, state); | |
358 | } else | |
359 | service_enter_dead(s, true, true); | |
360 | ||
361 | return; | |
362 | ||
363 | fail: | |
364 | log_warning("%s failed to kill processes: %s", name_id(NAME(s)), strerror(-r)); | |
365 | ||
366 | if (sent) { | |
367 | s->failure = true; | |
368 | service_set_state(s, state); | |
369 | } else if (state == SERVICE_STOP_SIGTERM || state == SERVICE_STOP_SIGKILL) | |
370 | service_enter_stop_post(s, false); | |
371 | else | |
372 | service_enter_dead(s, false, true); | |
373 | } | |
374 | ||
375 | static void service_enter_stop(Service *s, bool success) { | |
376 | int r; | |
377 | assert(s); | |
378 | ||
379 | if (!success) | |
380 | s->failure = true; | |
381 | ||
382 | if ((s->control_command = s->exec_command[SERVICE_EXEC_STOP])) { | |
383 | ||
384 | if ((r = service_spawn(s, s->control_command, true, &s->control_pid)) < 0) | |
385 | goto fail; | |
386 | ||
387 | service_set_state(s, SERVICE_STOP); | |
388 | } else | |
389 | service_enter_signal(s, SERVICE_STOP_SIGTERM, true); | |
390 | ||
391 | return; | |
392 | ||
393 | fail: | |
394 | log_warning("%s failed to run stop executable: %s", name_id(NAME(s)), strerror(-r)); | |
395 | service_enter_signal(s, SERVICE_STOP_SIGTERM, false); | |
396 | } | |
397 | ||
398 | static void service_enter_start_post(Service *s) { | |
399 | int r; | |
400 | assert(s); | |
401 | ||
402 | if ((s->control_command = s->exec_command[SERVICE_EXEC_START_POST])) { | |
403 | ||
404 | if ((r = service_spawn(s, s->control_command, true, &s->control_pid)) < 0) | |
405 | goto fail; | |
406 | ||
407 | service_set_state(s, SERVICE_START_POST); | |
408 | } else | |
409 | service_set_state(s, SERVICE_RUNNING); | |
410 | ||
411 | return; | |
412 | ||
413 | fail: | |
414 | log_warning("%s failed to run start-post executable: %s", name_id(NAME(s)), strerror(-r)); | |
415 | service_enter_stop(s, false); | |
416 | } | |
417 | ||
418 | static void service_enter_start(Service *s) { | |
419 | pid_t pid; | |
420 | int r; | |
421 | ||
422 | assert(s); | |
423 | ||
424 | assert(s->exec_command[SERVICE_EXEC_START]); | |
425 | assert(!s->exec_command[SERVICE_EXEC_START]->command_next); | |
426 | ||
427 | if ((r = service_spawn(s, s->exec_command[SERVICE_EXEC_START], s->type == SERVICE_FORKING, &pid)) < 0) | |
428 | goto fail; | |
429 | ||
430 | if (s->type == SERVICE_SIMPLE) { | |
431 | /* For simple services we immediately start | |
432 | * the START_POST binaries. */ | |
433 | ||
434 | s->main_pid = pid; | |
435 | s->main_pid_known = true; | |
436 | service_enter_start_post(s); | |
437 | ||
438 | } else if (s->type == SERVICE_FORKING) { | |
439 | ||
440 | /* For forking services we wait until the start | |
441 | * process exited. */ | |
442 | ||
443 | s->control_pid = pid; | |
444 | s->control_command = s->exec_command[SERVICE_EXEC_START]; | |
445 | service_set_state(s, SERVICE_START); | |
446 | } else | |
447 | assert_not_reached("Unknown service type"); | |
448 | ||
449 | return; | |
450 | ||
451 | fail: | |
452 | log_warning("%s failed to run start exectuable: %s", name_id(NAME(s)), strerror(-r)); | |
453 | service_enter_stop(s, false); | |
454 | } | |
455 | ||
456 | static void service_enter_start_pre(Service *s) { | |
457 | int r; | |
458 | ||
459 | assert(s); | |
460 | ||
461 | if ((s->control_command = s->exec_command[SERVICE_EXEC_START_PRE])) { | |
462 | ||
463 | if ((r = service_spawn(s, s->control_command, true, &s->control_pid)) < 0) | |
464 | goto fail; | |
465 | ||
466 | service_set_state(s, SERVICE_START_PRE); | |
467 | } else | |
468 | service_enter_start(s); | |
469 | ||
470 | return; | |
471 | ||
472 | fail: | |
473 | log_warning("%s failed to run start-pre executable: %s", name_id(NAME(s)), strerror(-r)); | |
474 | service_enter_dead(s, false, true); | |
475 | } | |
476 | ||
477 | static void service_enter_restart(Service *s) { | |
478 | int r; | |
479 | assert(s); | |
480 | ||
481 | if ((r = manager_add_job(NAME(s)->meta.manager, JOB_START, NAME(s), JOB_FAIL, false, NULL)) < 0) | |
482 | goto fail; | |
483 | ||
484 | log_debug("%s scheduled restart job.", name_id(NAME(s))); | |
485 | service_enter_dead(s, true, false); | |
486 | return; | |
487 | ||
488 | fail: | |
489 | ||
490 | log_warning("%s failed to schedule restart job: %s", name_id(NAME(s)), strerror(-r)); | |
491 | service_enter_dead(s, false, false); | |
492 | } | |
493 | ||
494 | static void service_enter_reload(Service *s) { | |
495 | int r; | |
496 | ||
497 | assert(s); | |
498 | ||
499 | if ((s->control_command = s->exec_command[SERVICE_EXEC_RELOAD])) { | |
500 | ||
501 | if ((r = service_spawn(s, s->control_command, true, &s->control_pid)) < 0) | |
502 | goto fail; | |
503 | ||
504 | service_set_state(s, SERVICE_RELOAD); | |
505 | } else | |
506 | service_set_state(s, SERVICE_RUNNING); | |
507 | ||
508 | return; | |
509 | ||
510 | fail: | |
511 | log_warning("%s failed to run reload executable: %s", name_id(NAME(s)), strerror(-r)); | |
512 | service_enter_stop(s, false); | |
513 | } | |
514 | ||
515 | static void service_run_next(Service *s, bool success) { | |
516 | int r; | |
517 | ||
518 | assert(s); | |
519 | assert(s->control_command); | |
520 | assert(s->control_command->command_next); | |
521 | ||
522 | if (!success) | |
523 | s->failure = true; | |
524 | ||
525 | s->control_command = s->control_command->command_next; | |
526 | ||
527 | if ((r = service_spawn(s, s->control_command, true, &s->control_pid)) < 0) | |
528 | goto fail; | |
529 | ||
530 | return; | |
531 | ||
532 | fail: | |
533 | log_warning("%s failed to run spawn next executable: %s", name_id(NAME(s)), strerror(-r)); | |
534 | ||
535 | if (s->state == SERVICE_STOP) | |
536 | service_enter_stop_post(s, false); | |
537 | else if (s->state == SERVICE_STOP_POST) | |
538 | service_enter_dead(s, false, true); | |
539 | else | |
540 | service_enter_stop(s, false); | |
5cb5a6ff LP |
541 | } |
542 | ||
543 | static int service_start(Name *n) { | |
544 | Service *s = SERVICE(n); | |
545 | ||
546 | assert(s); | |
547 | ||
034c6ed7 LP |
548 | /* We cannot fulfill this request right now, try again later |
549 | * please! */ | |
550 | if (s->state == SERVICE_STOP || | |
551 | s->state == SERVICE_STOP_SIGTERM || | |
552 | s->state == SERVICE_STOP_SIGKILL || | |
553 | s->state == SERVICE_STOP_POST || | |
554 | s->state == SERVICE_FINAL_SIGTERM || | |
555 | s->state == SERVICE_FINAL_SIGKILL) | |
5cb5a6ff LP |
556 | return -EAGAIN; |
557 | ||
034c6ed7 LP |
558 | /* Already on it! */ |
559 | if (s->state == SERVICE_START_PRE || | |
560 | s->state == SERVICE_START || | |
561 | s->state == SERVICE_START_POST) | |
562 | return 0; | |
563 | ||
564 | assert(s->state == SERVICE_DEAD || s->state == SERVICE_MAINTAINANCE || s->state == SERVICE_AUTO_RESTART); | |
5cb5a6ff | 565 | |
034c6ed7 LP |
566 | s->failure = false; |
567 | s->main_pid_known = false; | |
568 | ||
569 | service_enter_start_pre(s); | |
570 | return 0; | |
5cb5a6ff LP |
571 | } |
572 | ||
573 | static int service_stop(Name *n) { | |
574 | Service *s = SERVICE(n); | |
575 | ||
576 | assert(s); | |
577 | ||
034c6ed7 LP |
578 | if (s->state == SERVICE_START_PRE || |
579 | s->state == SERVICE_START || | |
580 | s->state == SERVICE_START_POST || | |
581 | s->state == SERVICE_RELOAD) | |
582 | return -EAGAIN; | |
583 | ||
584 | if (s->state == SERVICE_AUTO_RESTART) { | |
585 | service_set_state(s, SERVICE_DEAD); | |
586 | return 0; | |
587 | } | |
588 | ||
589 | assert(s->state == SERVICE_RUNNING); | |
5cb5a6ff | 590 | |
034c6ed7 | 591 | service_enter_stop(s, true); |
5cb5a6ff LP |
592 | return 0; |
593 | } | |
594 | ||
595 | static int service_reload(Name *n) { | |
034c6ed7 LP |
596 | Service *s = SERVICE(n); |
597 | ||
598 | assert(s); | |
599 | ||
600 | assert(s->state == SERVICE_RUNNING); | |
601 | ||
602 | service_enter_reload(s); | |
5cb5a6ff LP |
603 | return 0; |
604 | } | |
605 | ||
034c6ed7 LP |
606 | static bool service_can_reload(Name *n) { |
607 | Service *s = SERVICE(n); | |
608 | ||
609 | assert(s); | |
610 | ||
611 | return !!s->exec_command[SERVICE_EXEC_RELOAD]; | |
612 | } | |
613 | ||
5cb5a6ff | 614 | static NameActiveState service_active_state(Name *n) { |
034c6ed7 | 615 | assert(n); |
5cb5a6ff | 616 | |
034c6ed7 LP |
617 | return state_table[SERVICE(n)->state]; |
618 | } | |
619 | ||
620 | static int main_pid_good(Service *s) { | |
621 | assert(s); | |
622 | ||
623 | /* Returns 0 if the pid is dead, 1 if it is good, -1 if we | |
624 | * don't know */ | |
625 | ||
626 | /* If we know the pid file, then lets just check if it is | |
627 | * still valid */ | |
628 | if (s->main_pid_known) | |
629 | return s->main_pid > 0; | |
630 | ||
631 | /* We don't know the pid */ | |
632 | return -1; | |
633 | } | |
634 | ||
635 | static bool control_pid_good(Service *s) { | |
636 | assert(s); | |
5cb5a6ff | 637 | |
034c6ed7 | 638 | return s->control_pid > 0; |
5cb5a6ff LP |
639 | } |
640 | ||
034c6ed7 | 641 | static void service_sigchld_event(Name *n, pid_t pid, int code, int status) { |
5cb5a6ff | 642 | Service *s = SERVICE(n); |
034c6ed7 | 643 | bool success; |
5cb5a6ff LP |
644 | |
645 | assert(s); | |
034c6ed7 LP |
646 | assert(pid >= 0); |
647 | ||
648 | success = code == CLD_EXITED || status == 0; | |
649 | s->failure = s->failure || !success; | |
650 | ||
651 | if (s->main_pid == pid) { | |
652 | ||
653 | exec_status_fill(&s->main_exec_status, pid, code, status); | |
654 | s->main_pid = 0; | |
655 | ||
656 | if (s->type == SERVICE_SIMPLE) { | |
657 | assert(s->exec_command[SERVICE_EXEC_START]); | |
658 | s->exec_command[SERVICE_EXEC_START]->exec_status = s->main_exec_status; | |
659 | } | |
660 | ||
661 | log_debug("%s: main process exited, code=%s status=%i", name_id(n), sigchld_code(code), status); | |
662 | ||
663 | /* The service exited, so the service is officially | |
664 | * gone. */ | |
665 | ||
666 | switch (s->state) { | |
667 | ||
668 | case SERVICE_START_POST: | |
669 | case SERVICE_RELOAD: | |
670 | case SERVICE_STOP: | |
671 | /* Need to wait until the operation is | |
672 | * done */ | |
673 | break; | |
674 | ||
675 | case SERVICE_RUNNING: | |
676 | service_enter_stop(s, success); | |
677 | break; | |
678 | ||
679 | case SERVICE_STOP_SIGTERM: | |
680 | case SERVICE_STOP_SIGKILL: | |
681 | ||
682 | if (!control_pid_good(s)) | |
683 | service_enter_stop_post(s, success); | |
5cb5a6ff | 684 | |
034c6ed7 LP |
685 | /* If there is still a control process, wait for that first */ |
686 | break; | |
5cb5a6ff | 687 | |
034c6ed7 LP |
688 | default: |
689 | assert_not_reached("Uh, main process died at wrong time."); | |
690 | } | |
5cb5a6ff | 691 | |
034c6ed7 LP |
692 | } else if (s->control_pid == pid) { |
693 | assert(s->control_command); | |
694 | ||
695 | exec_status_fill(&s->control_command->exec_status, pid, code, status); | |
696 | s->control_pid = 0; | |
697 | ||
698 | log_debug("%s: control process exited, code=%s status=%i", name_id(n), sigchld_code(code), status); | |
699 | ||
700 | /* If we are shutting things down anyway we | |
701 | * don't care about failing commands. */ | |
702 | ||
703 | if (s->control_command->command_next && | |
704 | (success || (s->state == SERVICE_EXEC_STOP || s->state == SERVICE_EXEC_STOP_POST))) | |
705 | ||
706 | /* There is another command to * | |
707 | * execute, so let's do that. */ | |
708 | ||
709 | service_run_next(s, success); | |
710 | ||
711 | else { | |
712 | /* No further commands for this step, so let's | |
713 | * figure out what to do next */ | |
714 | ||
715 | switch (s->state) { | |
716 | ||
717 | case SERVICE_START_PRE: | |
718 | if (success) | |
719 | service_enter_start(s); | |
720 | else | |
721 | service_enter_stop(s, false); | |
722 | break; | |
723 | ||
724 | case SERVICE_START: | |
725 | assert(s->type == SERVICE_FORKING); | |
726 | ||
727 | /* Let's try to load the pid | |
728 | * file here if we can. We | |
729 | * ignore the return value, | |
730 | * since the PID file might | |
731 | * actually be created by a | |
732 | * START_POST script */ | |
733 | ||
734 | if (success) { | |
735 | if (s->pid_file) | |
736 | service_load_pid_file(s); | |
737 | ||
738 | service_enter_start_post(s); | |
739 | } else | |
740 | service_enter_stop(s, false); | |
741 | ||
742 | break; | |
743 | ||
744 | case SERVICE_START_POST: | |
745 | if (success && s->pid_file && !s->main_pid_known) { | |
746 | int r; | |
747 | ||
748 | /* Hmm, let's see if we can | |
749 | * load the pid now after the | |
750 | * start-post scripts got | |
751 | * executed. */ | |
752 | ||
753 | if ((r = service_load_pid_file(s)) < 0) | |
754 | log_warning("%s: failed to load PID file %s: %s", name_id(NAME(s)), s->pid_file, strerror(-r)); | |
755 | } | |
756 | ||
757 | /* Fall through */ | |
758 | ||
759 | case SERVICE_RELOAD: | |
760 | if (success) { | |
761 | if (main_pid_good(s) != 0) | |
762 | service_set_state(s, SERVICE_RUNNING); | |
763 | else | |
764 | service_enter_stop(s, true); | |
765 | } else | |
766 | service_enter_stop(s, false); | |
767 | ||
768 | break; | |
769 | ||
770 | case SERVICE_STOP: | |
771 | if (main_pid_good(s) > 0) | |
772 | /* Still not dead and we know the PID? Let's go hunting. */ | |
773 | service_enter_signal(s, SERVICE_STOP_SIGTERM, success); | |
774 | else | |
775 | service_enter_stop_post(s, success); | |
776 | break; | |
777 | ||
778 | case SERVICE_STOP_SIGTERM: | |
779 | case SERVICE_STOP_SIGKILL: | |
780 | if (main_pid_good(s) <= 0) | |
781 | service_enter_stop_post(s, success); | |
782 | ||
783 | /* If there is still a service | |
784 | * process around, wait until | |
785 | * that one quit, too */ | |
786 | break; | |
787 | ||
788 | case SERVICE_STOP_POST: | |
789 | case SERVICE_FINAL_SIGTERM: | |
790 | case SERVICE_FINAL_SIGKILL: | |
791 | service_enter_dead(s, success, true); | |
792 | break; | |
793 | ||
794 | default: | |
795 | assert_not_reached("Uh, control process died at wrong time."); | |
796 | } | |
797 | } | |
798 | } else | |
799 | assert_not_reached("Got SIGCHLD for unkown PID"); | |
800 | } | |
801 | ||
802 | static void service_timer_event(Name *n, int id, uint64_t elapsed) { | |
803 | Service *s = SERVICE(n); | |
804 | ||
805 | assert(s); | |
806 | assert(elapsed == 1); | |
807 | ||
808 | assert(s->timer_id == id); | |
809 | ||
810 | switch (s->state) { | |
811 | ||
812 | case SERVICE_START_PRE: | |
813 | case SERVICE_START: | |
814 | case SERVICE_START_POST: | |
815 | case SERVICE_RELOAD: | |
816 | log_warning("%s operation timed out. Stopping.", name_id(n)); | |
817 | service_enter_stop(s, false); | |
818 | break; | |
819 | ||
820 | case SERVICE_STOP: | |
821 | log_warning("%s stopping timed out. Terminating.", name_id(n)); | |
822 | service_enter_signal(s, SERVICE_STOP_SIGTERM, false); | |
823 | break; | |
824 | ||
825 | case SERVICE_STOP_SIGTERM: | |
826 | log_warning("%s stopping timed out. Killing.", name_id(n)); | |
827 | service_enter_signal(s, SERVICE_STOP_SIGKILL, false); | |
828 | break; | |
829 | ||
830 | case SERVICE_STOP_SIGKILL: | |
831 | /* Uh, wie sent a SIGKILL and it is still not gone? | |
832 | * Must be something we cannot kill, so let's just be | |
833 | * weirded out and continue */ | |
834 | ||
835 | log_warning("%s still around after SIGKILL. Ignoring.", name_id(n)); | |
836 | service_enter_stop_post(s, false); | |
837 | break; | |
838 | ||
839 | case SERVICE_STOP_POST: | |
840 | log_warning("%s stopping timed out (2). Terminating.", name_id(n)); | |
841 | service_enter_signal(s, SERVICE_FINAL_SIGTERM, false); | |
842 | break; | |
843 | ||
844 | case SERVICE_FINAL_SIGTERM: | |
845 | log_warning("%s stopping timed out (2). Killing.", name_id(n)); | |
846 | service_enter_signal(s, SERVICE_FINAL_SIGKILL, false); | |
847 | break; | |
848 | ||
849 | case SERVICE_FINAL_SIGKILL: | |
850 | log_warning("%s still around after SIGKILL (2). Entering maintainance mode.", name_id(n)); | |
851 | service_enter_dead(s, false, true); | |
852 | break; | |
853 | ||
854 | case SERVICE_AUTO_RESTART: | |
855 | log_debug("%s holdoff time over, scheduling restart.", name_id(n)); | |
856 | service_enter_restart(s); | |
857 | break; | |
858 | ||
859 | default: | |
860 | assert_not_reached("Timeout at wrong time."); | |
861 | } | |
5cb5a6ff LP |
862 | } |
863 | ||
864 | const NameVTable service_vtable = { | |
865 | .suffix = ".service", | |
866 | ||
034c6ed7 LP |
867 | .init = service_init, |
868 | .done = service_done, | |
869 | ||
5cb5a6ff LP |
870 | .dump = service_dump, |
871 | ||
872 | .start = service_start, | |
873 | .stop = service_stop, | |
874 | .reload = service_reload, | |
875 | ||
034c6ed7 LP |
876 | .can_reload = service_can_reload, |
877 | ||
5cb5a6ff LP |
878 | .active_state = service_active_state, |
879 | ||
034c6ed7 LP |
880 | .sigchld_event = service_sigchld_event, |
881 | .timer_event = service_timer_event, | |
5cb5a6ff | 882 | }; |