chiark / gitweb /
core: introduce new KillMode=mixed which sends SIGTERM only to the main process,...
[elogind.git] / src / core / scope.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2013 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 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   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <errno.h>
23 #include <signal.h>
24 #include <unistd.h>
25
26 #include "unit.h"
27 #include "scope.h"
28 #include "load-fragment.h"
29 #include "log.h"
30 #include "dbus-scope.h"
31 #include "special.h"
32 #include "unit-name.h"
33 #include "load-dropin.h"
34
35 static const UnitActiveState state_translation_table[_SCOPE_STATE_MAX] = {
36         [SCOPE_DEAD] = UNIT_INACTIVE,
37         [SCOPE_RUNNING] = UNIT_ACTIVE,
38         [SCOPE_STOP_SIGTERM] = UNIT_DEACTIVATING,
39         [SCOPE_STOP_SIGKILL] = UNIT_DEACTIVATING,
40         [SCOPE_FAILED] = UNIT_FAILED
41 };
42
43 static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
44
45 static void scope_init(Unit *u) {
46         Scope *s = SCOPE(u);
47
48         assert(u);
49         assert(u->load_state == UNIT_STUB);
50
51         s->timeout_stop_usec = u->manager->default_timeout_stop_usec;
52
53         cgroup_context_init(&s->cgroup_context);
54         kill_context_init(&s->kill_context);
55
56         UNIT(s)->ignore_on_isolate = true;
57         UNIT(s)->ignore_on_snapshot = true;
58 }
59
60 static void scope_done(Unit *u) {
61         Scope *s = SCOPE(u);
62
63         assert(u);
64
65         cgroup_context_done(&s->cgroup_context);
66
67         set_free(s->pids);
68         s->pids = NULL;
69
70         s->timer_event_source = sd_event_source_unref(s->timer_event_source);
71 }
72
73 static int scope_arm_timer(Scope *s) {
74         int r;
75
76         assert(s);
77
78         if (s->timeout_stop_usec <= 0) {
79                 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
80                 return 0;
81         }
82
83         if (s->timer_event_source) {
84                 r = sd_event_source_set_time(s->timer_event_source, now(CLOCK_MONOTONIC) + s->timeout_stop_usec);
85                 if (r < 0)
86                         return r;
87
88                 return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
89         }
90
91         return sd_event_add_monotonic(UNIT(s)->manager->event, now(CLOCK_MONOTONIC) + s->timeout_stop_usec, 0, scope_dispatch_timer, s, &s->timer_event_source);
92 }
93
94 static void scope_set_state(Scope *s, ScopeState state) {
95         ScopeState old_state;
96         assert(s);
97
98         old_state = s->state;
99         s->state = state;
100
101         if (state != SCOPE_STOP_SIGTERM &&
102             state != SCOPE_STOP_SIGKILL)
103                 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
104
105         if (state != old_state)
106                 log_debug("%s changed %s -> %s",
107                           UNIT(s)->id,
108                           scope_state_to_string(old_state),
109                           scope_state_to_string(state));
110
111         unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], true);
112 }
113
114 static int scope_add_default_dependencies(Scope *s) {
115         int r;
116
117         assert(s);
118
119         /* Make sure scopes are unloaded on shutdown */
120         r = unit_add_two_dependencies_by_name(
121                         UNIT(s),
122                         UNIT_BEFORE, UNIT_CONFLICTS,
123                         SPECIAL_SHUTDOWN_TARGET, NULL, true);
124         if (r < 0)
125                 return r;
126
127         return 0;
128 }
129
130 static int scope_verify(Scope *s) {
131         assert(s);
132
133         if (UNIT(s)->load_state != UNIT_LOADED)
134                 return 0;
135
136         if (set_size(s->pids) <= 0 && UNIT(s)->manager->n_reloading <= 0) {
137                 log_error_unit(UNIT(s)->id, "Scope %s has no PIDs. Refusing.", UNIT(s)->id);
138                 return -EINVAL;
139         }
140
141         return 0;
142 }
143
144 static int scope_load(Unit *u) {
145         Scope *s = SCOPE(u);
146         int r;
147
148         assert(s);
149         assert(u->load_state == UNIT_STUB);
150
151         if (!u->transient && UNIT(s)->manager->n_reloading <= 0)
152                 return -ENOENT;
153
154         u->load_state = UNIT_LOADED;
155
156         r = unit_load_dropin(u);
157         if (r < 0)
158                 return r;
159
160         r = unit_add_default_slice(u);
161         if (r < 0)
162                 return r;
163
164         if (u->default_dependencies) {
165                 r = scope_add_default_dependencies(s);
166                 if (r < 0)
167                         return r;
168         }
169
170         return scope_verify(s);
171 }
172
173 static int scope_coldplug(Unit *u) {
174         Scope *s = SCOPE(u);
175         int r;
176
177         assert(s);
178         assert(s->state == SCOPE_DEAD);
179
180         if (s->deserialized_state != s->state) {
181
182                 if (s->deserialized_state == SCOPE_STOP_SIGKILL || s->deserialized_state == SCOPE_STOP_SIGTERM) {
183                         r = scope_arm_timer(s);
184                         if (r < 0)
185                                 return r;
186                 }
187
188                 scope_set_state(s, s->deserialized_state);
189         }
190
191         return 0;
192 }
193
194 static void scope_dump(Unit *u, FILE *f, const char *prefix) {
195         Scope *s = SCOPE(u);
196
197         assert(s);
198         assert(f);
199
200         fprintf(f,
201                 "%sScope State: %s\n"
202                 "%sResult: %s\n",
203                 prefix, scope_state_to_string(s->state),
204                 prefix, scope_result_to_string(s->result));
205
206         cgroup_context_dump(&s->cgroup_context, f, prefix);
207         kill_context_dump(&s->kill_context, f, prefix);
208 }
209
210 static void scope_enter_dead(Scope *s, ScopeResult f) {
211         assert(s);
212
213         if (f != SCOPE_SUCCESS)
214                 s->result = f;
215
216         scope_set_state(s, s->result != SCOPE_SUCCESS ? SCOPE_FAILED : SCOPE_DEAD);
217 }
218
219 static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) {
220         int r;
221
222         assert(s);
223
224         if (f != SCOPE_SUCCESS)
225                 s->result = f;
226
227         r = unit_kill_context(
228                         UNIT(s),
229                         &s->kill_context,
230                         state != SCOPE_STOP_SIGTERM,
231                         -1, -1, false);
232         if (r < 0)
233                 goto fail;
234
235         if (r > 0) {
236                 r = scope_arm_timer(s);
237                 if (r < 0)
238                         goto fail;
239
240                 scope_set_state(s, state);
241         } else
242                 scope_enter_dead(s, SCOPE_SUCCESS);
243
244         return;
245
246 fail:
247         log_warning_unit(UNIT(s)->id,
248                          "%s failed to kill processes: %s", UNIT(s)->id, strerror(-r));
249
250         scope_enter_dead(s, SCOPE_FAILURE_RESOURCES);
251 }
252
253 static int scope_start(Unit *u) {
254         Scope *s = SCOPE(u);
255         int r;
256
257         assert(s);
258
259         if (s->state == SCOPE_FAILED)
260                 return -EPERM;
261
262         if (s->state == SCOPE_STOP_SIGTERM ||
263             s->state == SCOPE_STOP_SIGKILL)
264                 return -EAGAIN;
265
266         assert(s->state == SCOPE_DEAD);
267
268         if (!u->transient && UNIT(s)->manager->n_reloading <= 0)
269                 return -ENOENT;
270
271         r = unit_realize_cgroup(u);
272         if (r < 0) {
273                 log_error("Failed to realize cgroup: %s", strerror(-r));
274                 return r;
275         }
276
277         r = cg_attach_many_everywhere(u->manager->cgroup_supported, u->cgroup_path, s->pids);
278         if (r < 0)
279                 return r;
280
281         set_free(s->pids);
282         s->pids = NULL;
283
284         s->result = SCOPE_SUCCESS;
285
286         scope_set_state(s, SCOPE_RUNNING);
287         return 0;
288 }
289
290 static int scope_stop(Unit *u) {
291         Scope *s = SCOPE(u);
292
293         assert(s);
294         assert(s->state == SCOPE_RUNNING);
295
296         if (s->state == SCOPE_STOP_SIGTERM ||
297             s->state == SCOPE_STOP_SIGKILL)
298                 return 0;
299
300         assert(s->state == SCOPE_RUNNING);
301
302         scope_enter_signal(s, SCOPE_STOP_SIGTERM, SCOPE_SUCCESS);
303         return 0;
304 }
305
306 static void scope_reset_failed(Unit *u) {
307         Scope *s = SCOPE(u);
308
309         assert(s);
310
311         if (s->state == SCOPE_FAILED)
312                 scope_set_state(s, SCOPE_DEAD);
313
314         s->result = SCOPE_SUCCESS;
315 }
316
317 static int scope_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
318         return unit_kill_common(u, who, signo, -1, -1, error);
319 }
320
321 static int scope_get_timeout(Unit *u, uint64_t *timeout) {
322         Scope *s = SCOPE(u);
323         int r;
324
325         if (!s->timer_event_source)
326                 return 0;
327
328         r = sd_event_source_get_time(s->timer_event_source, timeout);
329         if (r < 0)
330                 return r;
331
332         return 1;
333 }
334
335 static int scope_serialize(Unit *u, FILE *f, FDSet *fds) {
336         Scope *s = SCOPE(u);
337
338         assert(s);
339         assert(f);
340         assert(fds);
341
342         unit_serialize_item(u, f, "state", scope_state_to_string(s->state));
343         return 0;
344 }
345
346 static int scope_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
347         Scope *s = SCOPE(u);
348
349         assert(u);
350         assert(key);
351         assert(value);
352         assert(fds);
353
354         if (streq(key, "state")) {
355                 ScopeState state;
356
357                 state = scope_state_from_string(value);
358                 if (state < 0)
359                         log_debug("Failed to parse state value %s", value);
360                 else
361                         s->deserialized_state = state;
362
363         } else
364                 log_debug("Unknown serialization key '%s'", key);
365
366         return 0;
367 }
368
369 static bool scope_check_gc(Unit *u) {
370         Scope *s = SCOPE(u);
371         int r;
372
373         assert(s);
374
375         /* Never clean up scopes that still have a process around,
376          * even if the scope is formally dead. */
377
378         if (UNIT(s)->cgroup_path) {
379                 r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, UNIT(s)->cgroup_path, true);
380                 if (r <= 0)
381                         return true;
382         }
383
384         return false;
385 }
386
387 static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
388         Scope *s = SCOPE(userdata);
389
390         assert(s);
391         assert(s->timer_event_source == source);
392
393         switch (s->state) {
394
395         case SCOPE_STOP_SIGTERM:
396                 if (s->kill_context.send_sigkill) {
397                         log_warning_unit(UNIT(s)->id, "%s stopping timed out. Killing.", UNIT(s)->id);
398                         scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_FAILURE_TIMEOUT);
399                 } else {
400                         log_warning_unit(UNIT(s)->id, "%s stopping timed out. Skipping SIGKILL.", UNIT(s)->id);
401                         scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
402                 }
403
404                 break;
405
406         case SCOPE_STOP_SIGKILL:
407                 log_warning_unit(UNIT(s)->id, "%s still around after SIGKILL. Ignoring.", UNIT(s)->id);
408                 scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
409                 break;
410
411         default:
412                 assert_not_reached("Timeout at wrong time.");
413         }
414
415         return 0;
416 }
417
418 static void scope_notify_cgroup_empty_event(Unit *u) {
419         Scope *s = SCOPE(u);
420         assert(u);
421
422         log_debug_unit(u->id, "%s: cgroup is empty", u->id);
423
424         switch (s->state) {
425
426         case SCOPE_RUNNING:
427         case SCOPE_STOP_SIGTERM:
428         case SCOPE_STOP_SIGKILL:
429                 scope_enter_dead(s, SCOPE_SUCCESS);
430
431                 break;
432
433         default:
434                 ;
435         }
436 }
437
438 _pure_ static UnitActiveState scope_active_state(Unit *u) {
439         assert(u);
440
441         return state_translation_table[SCOPE(u)->state];
442 }
443
444 _pure_ static const char *scope_sub_state_to_string(Unit *u) {
445         assert(u);
446
447         return scope_state_to_string(SCOPE(u)->state);
448 }
449
450 static const char* const scope_state_table[_SCOPE_STATE_MAX] = {
451         [SCOPE_DEAD] = "dead",
452         [SCOPE_RUNNING] = "running",
453         [SCOPE_STOP_SIGTERM] = "stop-sigterm",
454         [SCOPE_STOP_SIGKILL] = "stop-sigkill",
455         [SCOPE_FAILED] = "failed",
456 };
457
458 DEFINE_STRING_TABLE_LOOKUP(scope_state, ScopeState);
459
460 static const char* const scope_result_table[_SCOPE_RESULT_MAX] = {
461         [SCOPE_SUCCESS] = "success",
462         [SCOPE_FAILURE_RESOURCES] = "resources",
463         [SCOPE_FAILURE_TIMEOUT] = "timeout",
464 };
465
466 DEFINE_STRING_TABLE_LOOKUP(scope_result, ScopeResult);
467
468 const UnitVTable scope_vtable = {
469         .object_size = sizeof(Scope),
470         .cgroup_context_offset = offsetof(Scope, cgroup_context),
471         .kill_context_offset = offsetof(Scope, kill_context),
472
473         .sections =
474                 "Unit\0"
475                 "Scope\0"
476                 "Install\0",
477         .private_section = "Scope",
478
479         .no_alias = true,
480         .no_instances = true,
481
482         .init = scope_init,
483         .load = scope_load,
484         .done = scope_done,
485
486         .coldplug = scope_coldplug,
487
488         .dump = scope_dump,
489
490         .start = scope_start,
491         .stop = scope_stop,
492
493         .kill = scope_kill,
494
495         .get_timeout = scope_get_timeout,
496
497         .serialize = scope_serialize,
498         .deserialize_item = scope_deserialize_item,
499
500         .active_state = scope_active_state,
501         .sub_state_to_string = scope_sub_state_to_string,
502
503         .check_gc = scope_check_gc,
504
505         .reset_failed = scope_reset_failed,
506
507         .notify_cgroup_empty = scope_notify_cgroup_empty_event,
508
509         .bus_interface = "org.freedesktop.systemd1.Scope",
510         .bus_vtable = bus_scope_vtable,
511         .bus_set_property = bus_scope_set_property,
512         .bus_commit_properties = bus_scope_commit_properties,
513
514         .can_transient = true
515 };