]>
Commit | Line | Data |
---|---|---|
5cb5a6ff LP |
1 | /*-*- Mode: C; c-basic-offset: 8 -*-*/ |
2 | ||
a7334b09 LP |
3 | /*** |
4 | This file is part of systemd. | |
5 | ||
6 | Copyright 2010 Lennart Poettering | |
7 | ||
8 | systemd is free software; you can redistribute it and/or modify it | |
9 | under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation; either version 2 of the License, or | |
11 | (at your option) any later version. | |
12 | ||
13 | systemd is distributed in the hope that it will be useful, but | |
14 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with systemd; If not, see <http://www.gnu.org/licenses/>. | |
20 | ***/ | |
21 | ||
5cb5a6ff | 22 | #include <errno.h> |
034c6ed7 | 23 | #include <signal.h> |
5cb5a6ff | 24 | |
87f0e418 | 25 | #include "unit.h" |
5cb5a6ff LP |
26 | #include "service.h" |
27 | #include "load-fragment.h" | |
28 | #include "load-dropin.h" | |
034c6ed7 LP |
29 | #include "log.h" |
30 | ||
acbb0225 | 31 | static const UnitActiveState state_translation_table[_SERVICE_STATE_MAX] = { |
87f0e418 LP |
32 | [SERVICE_DEAD] = UNIT_INACTIVE, |
33 | [SERVICE_START_PRE] = UNIT_ACTIVATING, | |
34 | [SERVICE_START] = UNIT_ACTIVATING, | |
35 | [SERVICE_START_POST] = UNIT_ACTIVATING, | |
36 | [SERVICE_RUNNING] = UNIT_ACTIVE, | |
37 | [SERVICE_RELOAD] = UNIT_ACTIVE_RELOADING, | |
38 | [SERVICE_STOP] = UNIT_DEACTIVATING, | |
39 | [SERVICE_STOP_SIGTERM] = UNIT_DEACTIVATING, | |
40 | [SERVICE_STOP_SIGKILL] = UNIT_DEACTIVATING, | |
41 | [SERVICE_STOP_POST] = UNIT_DEACTIVATING, | |
42 | [SERVICE_FINAL_SIGTERM] = UNIT_DEACTIVATING, | |
43 | [SERVICE_FINAL_SIGKILL] = UNIT_DEACTIVATING, | |
44 | [SERVICE_MAINTAINANCE] = UNIT_INACTIVE, | |
45 | [SERVICE_AUTO_RESTART] = UNIT_ACTIVATING, | |
034c6ed7 | 46 | }; |
5cb5a6ff | 47 | |
87f0e418 LP |
48 | static void service_done(Unit *u) { |
49 | Service *s = SERVICE(u); | |
44d8db9e LP |
50 | |
51 | assert(s); | |
52 | ||
53 | free(s->pid_file); | |
54 | s->pid_file = NULL; | |
55 | ||
56 | exec_context_done(&s->exec_context); | |
57 | exec_command_free_array(s->exec_command, _SERVICE_EXEC_MAX); | |
58 | s->control_command = NULL; | |
59 | ||
60 | /* This will leak a process, but at least no memory or any of | |
61 | * our resources */ | |
62 | if (s->main_pid > 0) { | |
87f0e418 | 63 | unit_unwatch_pid(u, s->main_pid); |
44d8db9e LP |
64 | s->main_pid = 0; |
65 | } | |
66 | ||
67 | if (s->control_pid > 0) { | |
87f0e418 | 68 | unit_unwatch_pid(u, s->control_pid); |
44d8db9e LP |
69 | s->control_pid = 0; |
70 | } | |
71 | ||
acbb0225 | 72 | unit_unwatch_timer(u, &s->timer_watch); |
44d8db9e LP |
73 | } |
74 | ||
5cb5a6ff LP |
75 | static int service_load_sysv(Service *s) { |
76 | assert(s); | |
77 | ||
78 | /* Load service data from SysV init scripts, preferably with | |
79 | * LSB headers ... */ | |
80 | ||
81 | return -ENOENT; | |
82 | } | |
83 | ||
87f0e418 | 84 | static int service_init(Unit *u) { |
5cb5a6ff | 85 | int r; |
87f0e418 | 86 | Service *s = SERVICE(u); |
5cb5a6ff LP |
87 | |
88 | assert(s); | |
89 | ||
034c6ed7 LP |
90 | /* First, reset everything to the defaults, in case this is a |
91 | * reload */ | |
92 | ||
93 | s->type = 0; | |
94 | s->restart = 0; | |
95 | ||
96 | s->timeout_usec = DEFAULT_TIMEOUT_USEC; | |
97 | s->restart_usec = DEFAULT_RESTART_USEC; | |
98 | ||
99 | exec_context_init(&s->exec_context); | |
100 | ||
acbb0225 | 101 | s->timer_watch.type = WATCH_INVALID; |
034c6ed7 LP |
102 | |
103 | s->state = SERVICE_DEAD; | |
5cb5a6ff | 104 | |
1e2e8133 LP |
105 | RATELIMIT_INIT(s->ratelimit, 10*USEC_PER_SEC, 5); |
106 | ||
5cb5a6ff | 107 | /* Load a .service file */ |
d46de8a1 | 108 | if ((r = unit_load_fragment(u)) < 0) { |
87f0e418 | 109 | service_done(u); |
5cb5a6ff | 110 | return r; |
44d8db9e | 111 | } |
5cb5a6ff | 112 | |
d46de8a1 LP |
113 | /* Load a classic init script as a fallback, if we couldn*t find anything */ |
114 | if (r == 0) | |
115 | if ((r = service_load_sysv(s)) <= 0) { | |
116 | service_done(u); | |
117 | return r < 0 ? r : -ENOENT; | |
118 | } | |
119 | ||
5cb5a6ff | 120 | /* Load dropin directory data */ |
87f0e418 LP |
121 | if ((r = unit_load_dropin(u)) < 0) { |
122 | service_done(u); | |
5cb5a6ff | 123 | return r; |
034c6ed7 LP |
124 | } |
125 | ||
44d8db9e | 126 | return 0; |
034c6ed7 LP |
127 | } |
128 | ||
87f0e418 | 129 | static void service_dump(Unit *u, FILE *f, const char *prefix) { |
5cb5a6ff | 130 | |
5cb5a6ff | 131 | ServiceExecCommand c; |
87f0e418 | 132 | Service *s = SERVICE(u); |
44d8db9e | 133 | char *prefix2; |
5cb5a6ff LP |
134 | |
135 | assert(s); | |
136 | ||
44d8db9e LP |
137 | prefix2 = strappend(prefix, "\t"); |
138 | if (!prefix2) | |
139 | prefix2 = ""; | |
140 | ||
5cb5a6ff LP |
141 | fprintf(f, |
142 | "%sService State: %s\n", | |
94f04347 | 143 | prefix, service_state_to_string(s->state)); |
5cb5a6ff | 144 | |
034c6ed7 LP |
145 | if (s->pid_file) |
146 | fprintf(f, | |
147 | "%sPIDFile: %s\n", | |
148 | prefix, s->pid_file); | |
149 | ||
150 | ||
5cb5a6ff LP |
151 | exec_context_dump(&s->exec_context, f, prefix); |
152 | ||
153 | for (c = 0; c < _SERVICE_EXEC_MAX; c++) { | |
5cb5a6ff | 154 | |
44d8db9e LP |
155 | if (!s->exec_command[c]) |
156 | continue; | |
157 | ||
158 | fprintf(f, "%s→ %s:\n", | |
94f04347 | 159 | prefix, service_exec_command_to_string(c)); |
44d8db9e LP |
160 | |
161 | exec_command_dump_list(s->exec_command[c], f, prefix2); | |
5cb5a6ff | 162 | } |
44d8db9e LP |
163 | |
164 | free(prefix2); | |
5cb5a6ff LP |
165 | } |
166 | ||
034c6ed7 LP |
167 | static int service_load_pid_file(Service *s) { |
168 | char *k; | |
169 | unsigned long p; | |
170 | int r; | |
171 | ||
172 | assert(s); | |
173 | ||
174 | if (s->main_pid_known) | |
175 | return 0; | |
176 | ||
177 | if (!s->pid_file) | |
178 | return -ENOENT; | |
179 | ||
180 | if ((r = read_one_line_file(s->pid_file, &k)) < 0) | |
181 | return r; | |
182 | ||
183 | if ((r = safe_atolu(k, &p)) < 0) { | |
184 | free(k); | |
185 | return r; | |
186 | } | |
187 | ||
188 | if ((unsigned long) (pid_t) p != p) | |
189 | return -ERANGE; | |
190 | ||
191 | s->main_pid = p; | |
192 | s->main_pid_known = true; | |
193 | ||
194 | return 0; | |
195 | } | |
196 | ||
3e33402a LP |
197 | static int service_get_sockets(Service *s, Set **_set) { |
198 | Set *set; | |
ceee3d82 LP |
199 | Iterator i; |
200 | char *t; | |
3e33402a | 201 | int r; |
ceee3d82 LP |
202 | |
203 | assert(s); | |
3e33402a LP |
204 | assert(_set); |
205 | ||
206 | /* Collects all Socket objects that belong to this | |
207 | * service. Note that a service might have multiple sockets | |
208 | * via multiple names. */ | |
209 | ||
210 | if (!(set = set_new(NULL, NULL))) | |
211 | return -ENOMEM; | |
ceee3d82 LP |
212 | |
213 | SET_FOREACH(t, UNIT(s)->meta.names, i) { | |
214 | char *k; | |
215 | Unit *p; | |
216 | ||
217 | /* Look for all socket objects that go by any of our | |
218 | * units and collect their fds */ | |
219 | ||
3e33402a LP |
220 | if (!(k = unit_name_change_suffix(t, ".socket"))) { |
221 | r = -ENOMEM; | |
222 | goto fail; | |
223 | } | |
ceee3d82 LP |
224 | |
225 | p = manager_get_unit(UNIT(s)->meta.manager, k); | |
226 | free(k); | |
227 | ||
3e33402a | 228 | if (!p) continue; |
ceee3d82 | 229 | |
3e33402a LP |
230 | if ((r = set_put(set, p)) < 0) |
231 | goto fail; | |
ceee3d82 LP |
232 | } |
233 | ||
3e33402a LP |
234 | *_set = set; |
235 | return 0; | |
236 | ||
237 | fail: | |
238 | set_free(set); | |
239 | return r; | |
240 | } | |
241 | ||
242 | ||
243 | static int service_notify_sockets(Service *s) { | |
244 | Iterator i; | |
245 | Set *set; | |
246 | Socket *socket; | |
247 | int r; | |
248 | ||
249 | assert(s); | |
250 | ||
251 | /* Notifies all our sockets when we die */ | |
252 | ||
253 | if ((r = service_get_sockets(s, &set)) < 0) | |
254 | return r; | |
255 | ||
256 | SET_FOREACH(socket, set, i) | |
257 | socket_notify_service_dead(socket); | |
258 | ||
259 | set_free(set); | |
260 | ||
ceee3d82 LP |
261 | return 0; |
262 | } | |
263 | ||
034c6ed7 LP |
264 | static void service_set_state(Service *s, ServiceState state) { |
265 | ServiceState old_state; | |
5cb5a6ff LP |
266 | assert(s); |
267 | ||
034c6ed7 | 268 | old_state = s->state; |
5cb5a6ff | 269 | s->state = state; |
034c6ed7 LP |
270 | |
271 | if (state != SERVICE_START_PRE && | |
272 | state != SERVICE_START && | |
273 | state != SERVICE_START_POST && | |
274 | state != SERVICE_RELOAD && | |
275 | state != SERVICE_STOP && | |
276 | state != SERVICE_STOP_SIGTERM && | |
277 | state != SERVICE_STOP_SIGKILL && | |
278 | state != SERVICE_STOP_POST && | |
279 | state != SERVICE_FINAL_SIGTERM && | |
280 | state != SERVICE_FINAL_SIGKILL && | |
281 | state != SERVICE_AUTO_RESTART) | |
acbb0225 | 282 | unit_unwatch_timer(UNIT(s), &s->timer_watch); |
034c6ed7 | 283 | |
7d55e835 LP |
284 | if (state != SERVICE_START && |
285 | state != SERVICE_START_POST && | |
034c6ed7 LP |
286 | state != SERVICE_RUNNING && |
287 | state != SERVICE_RELOAD && | |
288 | state != SERVICE_STOP && | |
289 | state != SERVICE_STOP_SIGTERM && | |
290 | state != SERVICE_STOP_SIGKILL) | |
acbb0225 | 291 | if (s->main_pid > 0) { |
87f0e418 | 292 | unit_unwatch_pid(UNIT(s), s->main_pid); |
034c6ed7 LP |
293 | s->main_pid = 0; |
294 | } | |
295 | ||
296 | if (state != SERVICE_START_PRE && | |
297 | state != SERVICE_START && | |
298 | state != SERVICE_START_POST && | |
299 | state != SERVICE_RELOAD && | |
300 | state != SERVICE_STOP && | |
301 | state != SERVICE_STOP_SIGTERM && | |
302 | state != SERVICE_STOP_SIGKILL && | |
303 | state != SERVICE_STOP_POST && | |
304 | state != SERVICE_FINAL_SIGTERM && | |
305 | state != SERVICE_FINAL_SIGKILL) | |
acbb0225 | 306 | if (s->control_pid > 0) { |
87f0e418 | 307 | unit_unwatch_pid(UNIT(s), s->control_pid); |
034c6ed7 LP |
308 | s->control_pid = 0; |
309 | } | |
310 | ||
311 | if (state != SERVICE_START_PRE && | |
312 | state != SERVICE_START && | |
313 | state != SERVICE_START_POST && | |
314 | state != SERVICE_RELOAD && | |
315 | state != SERVICE_STOP && | |
316 | state != SERVICE_STOP_POST) | |
317 | s->control_command = NULL; | |
318 | ||
ceee3d82 LP |
319 | if (state == SERVICE_DEAD || |
320 | state == SERVICE_STOP || | |
321 | state == SERVICE_STOP_SIGTERM || | |
322 | state == SERVICE_STOP_SIGKILL || | |
323 | state == SERVICE_STOP_POST || | |
324 | state == SERVICE_FINAL_SIGTERM || | |
325 | state == SERVICE_FINAL_SIGKILL || | |
326 | state == SERVICE_MAINTAINANCE || | |
327 | state == SERVICE_AUTO_RESTART) | |
328 | service_notify_sockets(s); | |
329 | ||
94f04347 | 330 | log_debug("%s changed %s → %s", unit_id(UNIT(s)), service_state_to_string(old_state), service_state_to_string(state)); |
acbb0225 LP |
331 | |
332 | unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state]); | |
034c6ed7 LP |
333 | } |
334 | ||
44d8db9e LP |
335 | static int service_collect_fds(Service *s, int **fds, unsigned *n_fds) { |
336 | Iterator i; | |
337 | int r; | |
338 | int *rfds = NULL; | |
339 | unsigned rn_fds = 0; | |
3e33402a LP |
340 | Set *set; |
341 | Socket *socket; | |
44d8db9e LP |
342 | |
343 | assert(s); | |
344 | assert(fds); | |
345 | assert(n_fds); | |
346 | ||
3e33402a LP |
347 | if ((r = service_get_sockets(s, &set)) < 0) |
348 | return r; | |
349 | ||
350 | SET_FOREACH(socket, set, i) { | |
44d8db9e LP |
351 | int *cfds; |
352 | unsigned cn_fds; | |
353 | ||
3e33402a | 354 | if ((r = socket_collect_fds(socket, &cfds, &cn_fds)) < 0) |
44d8db9e LP |
355 | goto fail; |
356 | ||
357 | if (!cfds) | |
358 | continue; | |
359 | ||
360 | if (!rfds) { | |
361 | rfds = cfds; | |
362 | rn_fds = cn_fds; | |
363 | } else { | |
364 | int *t; | |
365 | ||
366 | if (!(t = new(int, rn_fds+cn_fds))) { | |
367 | free(cfds); | |
368 | r = -ENOMEM; | |
369 | goto fail; | |
370 | } | |
371 | ||
372 | memcpy(t, rfds, rn_fds); | |
373 | memcpy(t+rn_fds, cfds, cn_fds); | |
374 | free(rfds); | |
375 | free(cfds); | |
376 | ||
377 | rfds = t; | |
378 | rn_fds = rn_fds+cn_fds; | |
379 | } | |
380 | } | |
381 | ||
382 | *fds = rfds; | |
383 | *n_fds = rn_fds; | |
3e33402a LP |
384 | |
385 | set_free(set); | |
386 | ||
44d8db9e LP |
387 | return 0; |
388 | ||
389 | fail: | |
3e33402a | 390 | set_free(set); |
44d8db9e | 391 | free(rfds); |
3e33402a | 392 | |
44d8db9e LP |
393 | return r; |
394 | } | |
395 | ||
396 | static int service_spawn(Service *s, ExecCommand *c, bool timeout, bool pass_fds, pid_t *_pid) { | |
034c6ed7 LP |
397 | pid_t pid; |
398 | int r; | |
44d8db9e LP |
399 | int *fds = NULL; |
400 | unsigned n_fds = 0; | |
034c6ed7 LP |
401 | |
402 | assert(s); | |
403 | assert(c); | |
404 | assert(_pid); | |
405 | ||
44d8db9e LP |
406 | if (pass_fds) |
407 | if ((r = service_collect_fds(s, &fds, &n_fds)) < 0) | |
408 | goto fail; | |
409 | ||
034c6ed7 | 410 | if (timeout) { |
acbb0225 | 411 | if ((r = unit_watch_timer(UNIT(s), s->timeout_usec, &s->timer_watch)) < 0) |
034c6ed7 LP |
412 | goto fail; |
413 | } else | |
acbb0225 | 414 | unit_unwatch_timer(UNIT(s), &s->timer_watch); |
034c6ed7 | 415 | |
44d8db9e | 416 | if ((r = exec_spawn(c, &s->exec_context, fds, n_fds, &pid)) < 0) |
034c6ed7 LP |
417 | goto fail; |
418 | ||
87f0e418 | 419 | if ((r = unit_watch_pid(UNIT(s), pid)) < 0) |
034c6ed7 LP |
420 | /* FIXME: we need to do something here */ |
421 | goto fail; | |
422 | ||
44d8db9e | 423 | free(fds); |
034c6ed7 LP |
424 | *_pid = pid; |
425 | ||
5cb5a6ff | 426 | return 0; |
034c6ed7 LP |
427 | |
428 | fail: | |
44d8db9e LP |
429 | free(fds); |
430 | ||
034c6ed7 | 431 | if (timeout) |
acbb0225 | 432 | unit_unwatch_timer(UNIT(s), &s->timer_watch); |
034c6ed7 LP |
433 | |
434 | return r; | |
435 | } | |
436 | ||
437 | static void service_enter_dead(Service *s, bool success, bool allow_restart) { | |
438 | int r; | |
439 | assert(s); | |
440 | ||
441 | if (!success) | |
442 | s->failure = true; | |
443 | ||
444 | if (allow_restart && | |
445 | (s->restart == SERVICE_RESTART_ALWAYS || | |
446 | (s->restart == SERVICE_RESTART_ON_SUCCESS && !s->failure))) { | |
447 | ||
acbb0225 | 448 | if ((r = unit_watch_timer(UNIT(s), s->restart_usec, &s->timer_watch)) < 0) |
034c6ed7 LP |
449 | goto fail; |
450 | ||
451 | service_set_state(s, SERVICE_AUTO_RESTART); | |
452 | } else | |
453 | service_set_state(s, s->failure ? SERVICE_MAINTAINANCE : SERVICE_DEAD); | |
454 | ||
455 | return; | |
456 | ||
457 | fail: | |
87f0e418 | 458 | log_warning("%s failed to run install restart timer: %s", unit_id(UNIT(s)), strerror(-r)); |
034c6ed7 LP |
459 | service_enter_dead(s, false, false); |
460 | } | |
461 | ||
462 | static void service_enter_signal(Service *s, ServiceState state, bool success); | |
463 | ||
464 | static void service_enter_stop_post(Service *s, bool success) { | |
465 | int r; | |
466 | assert(s); | |
467 | ||
468 | if (!success) | |
469 | s->failure = true; | |
470 | ||
d6ea93e3 | 471 | if ((s->control_command = s->exec_command[SERVICE_EXEC_STOP_POST])) |
44d8db9e | 472 | if ((r = service_spawn(s, s->control_command, true, false, &s->control_pid)) < 0) |
034c6ed7 LP |
473 | goto fail; |
474 | ||
d6ea93e3 LP |
475 | |
476 | service_set_state(s, SERVICE_STOP_POST); | |
477 | ||
478 | if (!s->control_command) | |
034c6ed7 LP |
479 | service_enter_dead(s, true, true); |
480 | ||
481 | return; | |
482 | ||
483 | fail: | |
87f0e418 | 484 | log_warning("%s failed to run stop executable: %s", unit_id(UNIT(s)), strerror(-r)); |
034c6ed7 LP |
485 | service_enter_signal(s, SERVICE_FINAL_SIGTERM, false); |
486 | } | |
487 | ||
488 | static void service_enter_signal(Service *s, ServiceState state, bool success) { | |
489 | int r; | |
490 | bool sent = false; | |
491 | ||
492 | assert(s); | |
493 | ||
494 | if (!success) | |
495 | s->failure = true; | |
496 | ||
497 | if (s->main_pid > 0 || s->control_pid > 0) { | |
498 | int sig; | |
499 | ||
500 | sig = (state == SERVICE_STOP_SIGTERM || state == SERVICE_FINAL_SIGTERM) ? SIGTERM : SIGKILL; | |
501 | ||
502 | r = 0; | |
503 | if (s->main_pid > 0) { | |
504 | if (kill(s->main_pid, sig) < 0 && errno != ESRCH) | |
505 | r = -errno; | |
506 | else | |
507 | sent = true; | |
508 | } | |
509 | ||
510 | if (s->control_pid > 0) { | |
511 | if (kill(s->control_pid, sig) < 0 && errno != ESRCH) | |
512 | r = -errno; | |
513 | else | |
514 | sent = true; | |
515 | } | |
516 | ||
517 | if (r < 0) | |
518 | goto fail; | |
d6ea93e3 | 519 | } |
034c6ed7 | 520 | |
d6ea93e3 LP |
521 | service_set_state(s, state); |
522 | ||
523 | if (s->main_pid <= 0 && s->control_pid <= 0) | |
034c6ed7 LP |
524 | service_enter_dead(s, true, true); |
525 | ||
526 | return; | |
527 | ||
528 | fail: | |
87f0e418 | 529 | log_warning("%s failed to kill processes: %s", unit_id(UNIT(s)), strerror(-r)); |
034c6ed7 LP |
530 | |
531 | if (sent) { | |
532 | s->failure = true; | |
533 | service_set_state(s, state); | |
534 | } else if (state == SERVICE_STOP_SIGTERM || state == SERVICE_STOP_SIGKILL) | |
535 | service_enter_stop_post(s, false); | |
536 | else | |
537 | service_enter_dead(s, false, true); | |
538 | } | |
539 | ||
540 | static void service_enter_stop(Service *s, bool success) { | |
541 | int r; | |
542 | assert(s); | |
543 | ||
544 | if (!success) | |
545 | s->failure = true; | |
546 | ||
d6ea93e3 | 547 | if ((s->control_command = s->exec_command[SERVICE_EXEC_STOP])) |
44d8db9e | 548 | if ((r = service_spawn(s, s->control_command, true, false, &s->control_pid)) < 0) |
034c6ed7 LP |
549 | goto fail; |
550 | ||
d6ea93e3 LP |
551 | service_set_state(s, SERVICE_STOP); |
552 | ||
553 | if (!s->control_command) | |
034c6ed7 LP |
554 | service_enter_signal(s, SERVICE_STOP_SIGTERM, true); |
555 | ||
556 | return; | |
557 | ||
558 | fail: | |
87f0e418 | 559 | log_warning("%s failed to run stop executable: %s", unit_id(UNIT(s)), strerror(-r)); |
034c6ed7 LP |
560 | service_enter_signal(s, SERVICE_STOP_SIGTERM, false); |
561 | } | |
562 | ||
563 | static void service_enter_start_post(Service *s) { | |
564 | int r; | |
565 | assert(s); | |
566 | ||
d6ea93e3 | 567 | if ((s->control_command = s->exec_command[SERVICE_EXEC_START_POST])) |
44d8db9e | 568 | if ((r = service_spawn(s, s->control_command, true, false, &s->control_pid)) < 0) |
034c6ed7 LP |
569 | goto fail; |
570 | ||
d6ea93e3 LP |
571 | |
572 | service_set_state(s, SERVICE_START_POST); | |
573 | ||
574 | if (!s->control_command) | |
034c6ed7 LP |
575 | service_set_state(s, SERVICE_RUNNING); |
576 | ||
577 | return; | |
578 | ||
579 | fail: | |
87f0e418 | 580 | log_warning("%s failed to run start-post executable: %s", unit_id(UNIT(s)), strerror(-r)); |
034c6ed7 LP |
581 | service_enter_stop(s, false); |
582 | } | |
583 | ||
584 | static void service_enter_start(Service *s) { | |
585 | pid_t pid; | |
586 | int r; | |
587 | ||
588 | assert(s); | |
589 | ||
590 | assert(s->exec_command[SERVICE_EXEC_START]); | |
591 | assert(!s->exec_command[SERVICE_EXEC_START]->command_next); | |
592 | ||
44d8db9e | 593 | if ((r = service_spawn(s, s->exec_command[SERVICE_EXEC_START], s->type == SERVICE_FORKING, true, &pid)) < 0) |
034c6ed7 LP |
594 | goto fail; |
595 | ||
d6ea93e3 LP |
596 | service_set_state(s, SERVICE_START); |
597 | ||
034c6ed7 LP |
598 | if (s->type == SERVICE_SIMPLE) { |
599 | /* For simple services we immediately start | |
600 | * the START_POST binaries. */ | |
601 | ||
602 | s->main_pid = pid; | |
603 | s->main_pid_known = true; | |
604 | service_enter_start_post(s); | |
605 | ||
606 | } else if (s->type == SERVICE_FORKING) { | |
607 | ||
608 | /* For forking services we wait until the start | |
609 | * process exited. */ | |
610 | ||
611 | s->control_pid = pid; | |
612 | s->control_command = s->exec_command[SERVICE_EXEC_START]; | |
7d55e835 LP |
613 | } else if (s->type == SERVICE_FINISH) { |
614 | ||
615 | /* For finishing services we wait until the start | |
616 | * process exited, too, but it is our main process. */ | |
617 | ||
618 | s->main_pid = pid; | |
619 | s->control_command = s->exec_command[SERVICE_EXEC_START]; | |
034c6ed7 LP |
620 | } else |
621 | assert_not_reached("Unknown service type"); | |
622 | ||
623 | return; | |
624 | ||
625 | fail: | |
87f0e418 | 626 | log_warning("%s failed to run start exectuable: %s", unit_id(UNIT(s)), strerror(-r)); |
034c6ed7 LP |
627 | service_enter_stop(s, false); |
628 | } | |
629 | ||
630 | static void service_enter_start_pre(Service *s) { | |
631 | int r; | |
632 | ||
633 | assert(s); | |
634 | ||
d6ea93e3 | 635 | if ((s->control_command = s->exec_command[SERVICE_EXEC_START_PRE])) |
44d8db9e | 636 | if ((r = service_spawn(s, s->control_command, true, false, &s->control_pid)) < 0) |
034c6ed7 LP |
637 | goto fail; |
638 | ||
d6ea93e3 LP |
639 | service_set_state(s, SERVICE_START_PRE); |
640 | ||
641 | if (!s->control_command) | |
034c6ed7 LP |
642 | service_enter_start(s); |
643 | ||
644 | return; | |
645 | ||
646 | fail: | |
87f0e418 | 647 | log_warning("%s failed to run start-pre executable: %s", unit_id(UNIT(s)), strerror(-r)); |
034c6ed7 LP |
648 | service_enter_dead(s, false, true); |
649 | } | |
650 | ||
651 | static void service_enter_restart(Service *s) { | |
652 | int r; | |
653 | assert(s); | |
654 | ||
87f0e418 | 655 | if ((r = manager_add_job(UNIT(s)->meta.manager, JOB_START, UNIT(s), JOB_FAIL, false, NULL)) < 0) |
034c6ed7 LP |
656 | goto fail; |
657 | ||
87f0e418 | 658 | log_debug("%s scheduled restart job.", unit_id(UNIT(s))); |
034c6ed7 LP |
659 | service_enter_dead(s, true, false); |
660 | return; | |
661 | ||
662 | fail: | |
663 | ||
87f0e418 | 664 | log_warning("%s failed to schedule restart job: %s", unit_id(UNIT(s)), strerror(-r)); |
034c6ed7 LP |
665 | service_enter_dead(s, false, false); |
666 | } | |
667 | ||
668 | static void service_enter_reload(Service *s) { | |
669 | int r; | |
670 | ||
671 | assert(s); | |
672 | ||
d6ea93e3 | 673 | if ((s->control_command = s->exec_command[SERVICE_EXEC_RELOAD])) |
44d8db9e | 674 | if ((r = service_spawn(s, s->control_command, true, false, &s->control_pid)) < 0) |
034c6ed7 LP |
675 | goto fail; |
676 | ||
d6ea93e3 LP |
677 | service_set_state(s, SERVICE_RELOAD); |
678 | ||
679 | if (!s->control_command) | |
034c6ed7 LP |
680 | service_set_state(s, SERVICE_RUNNING); |
681 | ||
682 | return; | |
683 | ||
684 | fail: | |
87f0e418 | 685 | log_warning("%s failed to run reload executable: %s", unit_id(UNIT(s)), strerror(-r)); |
034c6ed7 LP |
686 | service_enter_stop(s, false); |
687 | } | |
688 | ||
689 | static void service_run_next(Service *s, bool success) { | |
690 | int r; | |
691 | ||
692 | assert(s); | |
693 | assert(s->control_command); | |
694 | assert(s->control_command->command_next); | |
695 | ||
696 | if (!success) | |
697 | s->failure = true; | |
698 | ||
699 | s->control_command = s->control_command->command_next; | |
700 | ||
44d8db9e | 701 | if ((r = service_spawn(s, s->control_command, true, false, &s->control_pid)) < 0) |
034c6ed7 LP |
702 | goto fail; |
703 | ||
704 | return; | |
705 | ||
706 | fail: | |
87f0e418 | 707 | log_warning("%s failed to run spawn next executable: %s", unit_id(UNIT(s)), strerror(-r)); |
034c6ed7 LP |
708 | |
709 | if (s->state == SERVICE_STOP) | |
710 | service_enter_stop_post(s, false); | |
711 | else if (s->state == SERVICE_STOP_POST) | |
712 | service_enter_dead(s, false, true); | |
713 | else | |
714 | service_enter_stop(s, false); | |
5cb5a6ff LP |
715 | } |
716 | ||
87f0e418 LP |
717 | static int service_start(Unit *u) { |
718 | Service *s = SERVICE(u); | |
5cb5a6ff LP |
719 | |
720 | assert(s); | |
721 | ||
034c6ed7 LP |
722 | /* We cannot fulfill this request right now, try again later |
723 | * please! */ | |
724 | if (s->state == SERVICE_STOP || | |
725 | s->state == SERVICE_STOP_SIGTERM || | |
726 | s->state == SERVICE_STOP_SIGKILL || | |
727 | s->state == SERVICE_STOP_POST || | |
728 | s->state == SERVICE_FINAL_SIGTERM || | |
729 | s->state == SERVICE_FINAL_SIGKILL) | |
5cb5a6ff LP |
730 | return -EAGAIN; |
731 | ||
034c6ed7 LP |
732 | /* Already on it! */ |
733 | if (s->state == SERVICE_START_PRE || | |
734 | s->state == SERVICE_START || | |
735 | s->state == SERVICE_START_POST) | |
736 | return 0; | |
737 | ||
738 | assert(s->state == SERVICE_DEAD || s->state == SERVICE_MAINTAINANCE || s->state == SERVICE_AUTO_RESTART); | |
5cb5a6ff | 739 | |
1e2e8133 LP |
740 | /* Make sure we don't enter a busy loop of some kind. */ |
741 | if (!ratelimit_test(&s->ratelimit)) { | |
742 | log_warning("%s start request repeated too quickly, refusing to start.", unit_id(u)); | |
743 | return -EAGAIN; | |
744 | } | |
745 | ||
034c6ed7 LP |
746 | s->failure = false; |
747 | s->main_pid_known = false; | |
748 | ||
749 | service_enter_start_pre(s); | |
750 | return 0; | |
5cb5a6ff LP |
751 | } |
752 | ||
87f0e418 LP |
753 | static int service_stop(Unit *u) { |
754 | Service *s = SERVICE(u); | |
5cb5a6ff LP |
755 | |
756 | assert(s); | |
757 | ||
034c6ed7 LP |
758 | if (s->state == SERVICE_START_PRE || |
759 | s->state == SERVICE_START || | |
760 | s->state == SERVICE_START_POST || | |
761 | s->state == SERVICE_RELOAD) | |
762 | return -EAGAIN; | |
763 | ||
764 | if (s->state == SERVICE_AUTO_RESTART) { | |
765 | service_set_state(s, SERVICE_DEAD); | |
766 | return 0; | |
767 | } | |
768 | ||
769 | assert(s->state == SERVICE_RUNNING); | |
5cb5a6ff | 770 | |
034c6ed7 | 771 | service_enter_stop(s, true); |
5cb5a6ff LP |
772 | return 0; |
773 | } | |
774 | ||
87f0e418 LP |
775 | static int service_reload(Unit *u) { |
776 | Service *s = SERVICE(u); | |
034c6ed7 LP |
777 | |
778 | assert(s); | |
779 | ||
780 | assert(s->state == SERVICE_RUNNING); | |
781 | ||
782 | service_enter_reload(s); | |
5cb5a6ff LP |
783 | return 0; |
784 | } | |
785 | ||
87f0e418 LP |
786 | static bool service_can_reload(Unit *u) { |
787 | Service *s = SERVICE(u); | |
034c6ed7 LP |
788 | |
789 | assert(s); | |
790 | ||
791 | return !!s->exec_command[SERVICE_EXEC_RELOAD]; | |
792 | } | |
793 | ||
87f0e418 LP |
794 | static UnitActiveState service_active_state(Unit *u) { |
795 | assert(u); | |
5cb5a6ff | 796 | |
acbb0225 | 797 | return state_translation_table[SERVICE(u)->state]; |
034c6ed7 LP |
798 | } |
799 | ||
800 | static int main_pid_good(Service *s) { | |
801 | assert(s); | |
802 | ||
803 | /* Returns 0 if the pid is dead, 1 if it is good, -1 if we | |
804 | * don't know */ | |
805 | ||
806 | /* If we know the pid file, then lets just check if it is | |
807 | * still valid */ | |
808 | if (s->main_pid_known) | |
809 | return s->main_pid > 0; | |
810 | ||
811 | /* We don't know the pid */ | |
812 | return -1; | |
813 | } | |
814 | ||
815 | static bool control_pid_good(Service *s) { | |
816 | assert(s); | |
5cb5a6ff | 817 | |
034c6ed7 | 818 | return s->control_pid > 0; |
5cb5a6ff LP |
819 | } |
820 | ||
87f0e418 LP |
821 | static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { |
822 | Service *s = SERVICE(u); | |
034c6ed7 | 823 | bool success; |
5cb5a6ff LP |
824 | |
825 | assert(s); | |
034c6ed7 LP |
826 | assert(pid >= 0); |
827 | ||
bd982a8b | 828 | success = code == CLD_EXITED && status == 0; |
034c6ed7 LP |
829 | s->failure = s->failure || !success; |
830 | ||
831 | if (s->main_pid == pid) { | |
832 | ||
833 | exec_status_fill(&s->main_exec_status, pid, code, status); | |
834 | s->main_pid = 0; | |
835 | ||
7d55e835 | 836 | if (s->type == SERVICE_SIMPLE || s->type == SERVICE_FINISH) { |
034c6ed7 LP |
837 | assert(s->exec_command[SERVICE_EXEC_START]); |
838 | s->exec_command[SERVICE_EXEC_START]->exec_status = s->main_exec_status; | |
839 | } | |
840 | ||
94f04347 | 841 | log_debug("%s: main process exited, code=%s status=%i", unit_id(u), sigchld_code_to_string(code), status); |
034c6ed7 LP |
842 | |
843 | /* The service exited, so the service is officially | |
844 | * gone. */ | |
845 | ||
846 | switch (s->state) { | |
847 | ||
848 | case SERVICE_START_POST: | |
849 | case SERVICE_RELOAD: | |
850 | case SERVICE_STOP: | |
851 | /* Need to wait until the operation is | |
852 | * done */ | |
853 | break; | |
854 | ||
7d55e835 LP |
855 | case SERVICE_START: |
856 | assert(s->type == SERVICE_FINISH); | |
857 | ||
858 | /* This was our main goal, so let's go on */ | |
859 | if (success) | |
860 | service_enter_start_post(s); | |
861 | else | |
862 | service_enter_stop(s, false); | |
863 | break; | |
864 | ||
034c6ed7 LP |
865 | case SERVICE_RUNNING: |
866 | service_enter_stop(s, success); | |
867 | break; | |
868 | ||
869 | case SERVICE_STOP_SIGTERM: | |
870 | case SERVICE_STOP_SIGKILL: | |
871 | ||
872 | if (!control_pid_good(s)) | |
873 | service_enter_stop_post(s, success); | |
5cb5a6ff | 874 | |
034c6ed7 LP |
875 | /* If there is still a control process, wait for that first */ |
876 | break; | |
5cb5a6ff | 877 | |
034c6ed7 LP |
878 | default: |
879 | assert_not_reached("Uh, main process died at wrong time."); | |
880 | } | |
5cb5a6ff | 881 | |
034c6ed7 LP |
882 | } else if (s->control_pid == pid) { |
883 | assert(s->control_command); | |
884 | ||
885 | exec_status_fill(&s->control_command->exec_status, pid, code, status); | |
886 | s->control_pid = 0; | |
887 | ||
94f04347 | 888 | log_debug("%s: control process exited, code=%s status=%i", unit_id(u), sigchld_code_to_string(code), status); |
034c6ed7 LP |
889 | |
890 | /* If we are shutting things down anyway we | |
891 | * don't care about failing commands. */ | |
892 | ||
893 | if (s->control_command->command_next && | |
894 | (success || (s->state == SERVICE_EXEC_STOP || s->state == SERVICE_EXEC_STOP_POST))) | |
895 | ||
896 | /* There is another command to * | |
897 | * execute, so let's do that. */ | |
898 | ||
899 | service_run_next(s, success); | |
900 | ||
901 | else { | |
902 | /* No further commands for this step, so let's | |
903 | * figure out what to do next */ | |
904 | ||
94f04347 | 905 | log_debug("%s got final SIGCHLD for state %s", unit_id(u), service_state_to_string(s->state)); |
bd982a8b | 906 | |
034c6ed7 LP |
907 | switch (s->state) { |
908 | ||
909 | case SERVICE_START_PRE: | |
910 | if (success) | |
911 | service_enter_start(s); | |
912 | else | |
913 | service_enter_stop(s, false); | |
914 | break; | |
915 | ||
916 | case SERVICE_START: | |
917 | assert(s->type == SERVICE_FORKING); | |
918 | ||
919 | /* Let's try to load the pid | |
920 | * file here if we can. We | |
921 | * ignore the return value, | |
922 | * since the PID file might | |
923 | * actually be created by a | |
924 | * START_POST script */ | |
925 | ||
926 | if (success) { | |
927 | if (s->pid_file) | |
928 | service_load_pid_file(s); | |
929 | ||
930 | service_enter_start_post(s); | |
931 | } else | |
932 | service_enter_stop(s, false); | |
933 | ||
934 | break; | |
935 | ||
936 | case SERVICE_START_POST: | |
937 | if (success && s->pid_file && !s->main_pid_known) { | |
938 | int r; | |
939 | ||
940 | /* Hmm, let's see if we can | |
941 | * load the pid now after the | |
942 | * start-post scripts got | |
943 | * executed. */ | |
944 | ||
945 | if ((r = service_load_pid_file(s)) < 0) | |
87f0e418 | 946 | log_warning("%s: failed to load PID file %s: %s", unit_id(UNIT(s)), s->pid_file, strerror(-r)); |
034c6ed7 LP |
947 | } |
948 | ||
949 | /* Fall through */ | |
950 | ||
951 | case SERVICE_RELOAD: | |
952 | if (success) { | |
953 | if (main_pid_good(s) != 0) | |
954 | service_set_state(s, SERVICE_RUNNING); | |
955 | else | |
956 | service_enter_stop(s, true); | |
957 | } else | |
958 | service_enter_stop(s, false); | |
959 | ||
960 | break; | |
961 | ||
962 | case SERVICE_STOP: | |
963 | if (main_pid_good(s) > 0) | |
964 | /* Still not dead and we know the PID? Let's go hunting. */ | |
965 | service_enter_signal(s, SERVICE_STOP_SIGTERM, success); | |
966 | else | |
967 | service_enter_stop_post(s, success); | |
968 | break; | |
969 | ||
970 | case SERVICE_STOP_SIGTERM: | |
971 | case SERVICE_STOP_SIGKILL: | |
972 | if (main_pid_good(s) <= 0) | |
973 | service_enter_stop_post(s, success); | |
974 | ||
975 | /* If there is still a service | |
976 | * process around, wait until | |
977 | * that one quit, too */ | |
978 | break; | |
979 | ||
980 | case SERVICE_STOP_POST: | |
981 | case SERVICE_FINAL_SIGTERM: | |
982 | case SERVICE_FINAL_SIGKILL: | |
983 | service_enter_dead(s, success, true); | |
984 | break; | |
985 | ||
986 | default: | |
987 | assert_not_reached("Uh, control process died at wrong time."); | |
988 | } | |
989 | } | |
990 | } else | |
991 | assert_not_reached("Got SIGCHLD for unkown PID"); | |
992 | } | |
993 | ||
acbb0225 | 994 | static void service_timer_event(Unit *u, uint64_t elapsed, Watch* w) { |
87f0e418 | 995 | Service *s = SERVICE(u); |
034c6ed7 LP |
996 | |
997 | assert(s); | |
998 | assert(elapsed == 1); | |
999 | ||
acbb0225 | 1000 | assert(w == &s->timer_watch); |
034c6ed7 LP |
1001 | |
1002 | switch (s->state) { | |
1003 | ||
1004 | case SERVICE_START_PRE: | |
1005 | case SERVICE_START: | |
1006 | case SERVICE_START_POST: | |
1007 | case SERVICE_RELOAD: | |
87f0e418 | 1008 | log_warning("%s operation timed out. Stopping.", unit_id(u)); |
034c6ed7 LP |
1009 | service_enter_stop(s, false); |
1010 | break; | |
1011 | ||
1012 | case SERVICE_STOP: | |
87f0e418 | 1013 | log_warning("%s stopping timed out. Terminating.", unit_id(u)); |
034c6ed7 LP |
1014 | service_enter_signal(s, SERVICE_STOP_SIGTERM, false); |
1015 | break; | |
1016 | ||
1017 | case SERVICE_STOP_SIGTERM: | |
87f0e418 | 1018 | log_warning("%s stopping timed out. Killing.", unit_id(u)); |
034c6ed7 LP |
1019 | service_enter_signal(s, SERVICE_STOP_SIGKILL, false); |
1020 | break; | |
1021 | ||
1022 | case SERVICE_STOP_SIGKILL: | |
1023 | /* Uh, wie sent a SIGKILL and it is still not gone? | |
1024 | * Must be something we cannot kill, so let's just be | |
1025 | * weirded out and continue */ | |
1026 | ||
87f0e418 | 1027 | log_warning("%s still around after SIGKILL. Ignoring.", unit_id(u)); |
034c6ed7 LP |
1028 | service_enter_stop_post(s, false); |
1029 | break; | |
1030 | ||
1031 | case SERVICE_STOP_POST: | |
87f0e418 | 1032 | log_warning("%s stopping timed out (2). Terminating.", unit_id(u)); |
034c6ed7 LP |
1033 | service_enter_signal(s, SERVICE_FINAL_SIGTERM, false); |
1034 | break; | |
1035 | ||
1036 | case SERVICE_FINAL_SIGTERM: | |
87f0e418 | 1037 | log_warning("%s stopping timed out (2). Killing.", unit_id(u)); |
034c6ed7 LP |
1038 | service_enter_signal(s, SERVICE_FINAL_SIGKILL, false); |
1039 | break; | |
1040 | ||
1041 | case SERVICE_FINAL_SIGKILL: | |
87f0e418 | 1042 | log_warning("%s still around after SIGKILL (2). Entering maintainance mode.", unit_id(u)); |
034c6ed7 LP |
1043 | service_enter_dead(s, false, true); |
1044 | break; | |
1045 | ||
1046 | case SERVICE_AUTO_RESTART: | |
87f0e418 | 1047 | log_debug("%s holdoff time over, scheduling restart.", unit_id(u)); |
034c6ed7 LP |
1048 | service_enter_restart(s); |
1049 | break; | |
1050 | ||
1051 | default: | |
1052 | assert_not_reached("Timeout at wrong time."); | |
1053 | } | |
5cb5a6ff LP |
1054 | } |
1055 | ||
94f04347 LP |
1056 | static const char* const service_state_table[_SERVICE_STATE_MAX] = { |
1057 | [SERVICE_DEAD] = "dead", | |
1058 | [SERVICE_START_PRE] = "start-pre", | |
1059 | [SERVICE_START] = "start", | |
1060 | [SERVICE_START_POST] = "start-post", | |
1061 | [SERVICE_RUNNING] = "running", | |
1062 | [SERVICE_RELOAD] = "reload", | |
1063 | [SERVICE_STOP] = "stop", | |
1064 | [SERVICE_STOP_SIGTERM] = "stop-sigterm", | |
1065 | [SERVICE_STOP_SIGKILL] = "stop-sigkill", | |
1066 | [SERVICE_STOP_POST] = "stop-post", | |
1067 | [SERVICE_FINAL_SIGTERM] = "final-sigterm", | |
1068 | [SERVICE_FINAL_SIGKILL] = "final-sigkill", | |
1069 | [SERVICE_MAINTAINANCE] = "maintainance", | |
1070 | [SERVICE_AUTO_RESTART] = "auto-restart", | |
1071 | }; | |
1072 | ||
1073 | DEFINE_STRING_TABLE_LOOKUP(service_state, ServiceState); | |
1074 | ||
1075 | static const char* const service_restart_table[_SERVICE_RESTART_MAX] = { | |
1076 | [SERVICE_ONCE] = "once", | |
1077 | [SERVICE_RESTART_ON_SUCCESS] = "restart-on-success", | |
1078 | [SERVICE_RESTART_ALWAYS] = "restart-on-failure", | |
1079 | }; | |
1080 | ||
1081 | DEFINE_STRING_TABLE_LOOKUP(service_restart, ServiceRestart); | |
1082 | ||
1083 | static const char* const service_type_table[_SERVICE_TYPE_MAX] = { | |
1084 | [SERVICE_FORKING] = "forking", | |
1085 | [SERVICE_SIMPLE] = "simple", | |
1086 | [SERVICE_FINISH] = "finish" | |
1087 | }; | |
1088 | ||
1089 | DEFINE_STRING_TABLE_LOOKUP(service_type, ServiceType); | |
1090 | ||
1091 | static const char* const service_exec_command_table[_SERVICE_EXEC_MAX] = { | |
1092 | [SERVICE_EXEC_START_PRE] = "ExecStartPre", | |
1093 | [SERVICE_EXEC_START] = "ExecStart", | |
1094 | [SERVICE_EXEC_START_POST] = "ExecStartPost", | |
1095 | [SERVICE_EXEC_RELOAD] = "ExecReload", | |
1096 | [SERVICE_EXEC_STOP] = "ExecStop", | |
1097 | [SERVICE_EXEC_STOP_POST] = "ExecStopPost", | |
1098 | }; | |
1099 | ||
1100 | DEFINE_STRING_TABLE_LOOKUP(service_exec_command, ServiceExecCommand); | |
1101 | ||
87f0e418 | 1102 | const UnitVTable service_vtable = { |
5cb5a6ff LP |
1103 | .suffix = ".service", |
1104 | ||
034c6ed7 LP |
1105 | .init = service_init, |
1106 | .done = service_done, | |
1107 | ||
5cb5a6ff LP |
1108 | .dump = service_dump, |
1109 | ||
1110 | .start = service_start, | |
1111 | .stop = service_stop, | |
1112 | .reload = service_reload, | |
1113 | ||
034c6ed7 LP |
1114 | .can_reload = service_can_reload, |
1115 | ||
5cb5a6ff LP |
1116 | .active_state = service_active_state, |
1117 | ||
034c6ed7 LP |
1118 | .sigchld_event = service_sigchld_event, |
1119 | .timer_event = service_timer_event, | |
5cb5a6ff | 1120 | }; |