chiark / gitweb /
core: rework context initialization/destruction logic
[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_ABANDONED] = UNIT_ACTIVE,
39         [SCOPE_STOP_SIGTERM] = UNIT_DEACTIVATING,
40         [SCOPE_STOP_SIGKILL] = UNIT_DEACTIVATING,
41         [SCOPE_FAILED] = UNIT_FAILED
42 };
43
44 static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
45
46 static void scope_init(Unit *u) {
47         Scope *s = SCOPE(u);
48
49         assert(u);
50         assert(u->load_state == UNIT_STUB);
51
52         s->timeout_stop_usec = u->manager->default_timeout_stop_usec;
53
54         UNIT(s)->ignore_on_isolate = true;
55         UNIT(s)->ignore_on_snapshot = true;
56 }
57
58 static void scope_done(Unit *u) {
59         Scope *s = SCOPE(u);
60
61         assert(u);
62
63         free(s->controller);
64
65         s->timer_event_source = sd_event_source_unref(s->timer_event_source);
66 }
67
68 static int scope_arm_timer(Scope *s) {
69         int r;
70
71         assert(s);
72
73         if (s->timeout_stop_usec <= 0) {
74                 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
75                 return 0;
76         }
77
78         if (s->timer_event_source) {
79                 r = sd_event_source_set_time(s->timer_event_source, now(CLOCK_MONOTONIC) + s->timeout_stop_usec);
80                 if (r < 0)
81                         return r;
82
83                 return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
84         }
85
86         return sd_event_add_monotonic(UNIT(s)->manager->event, &s->timer_event_source, now(CLOCK_MONOTONIC) + s->timeout_stop_usec, 0, scope_dispatch_timer, s);
87 }
88
89 static void scope_set_state(Scope *s, ScopeState state) {
90         ScopeState old_state;
91         assert(s);
92
93         old_state = s->state;
94         s->state = state;
95
96         if (!IN_SET(state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL))
97                 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
98
99         if (IN_SET(state, SCOPE_DEAD, SCOPE_FAILED))
100                 unit_unwatch_all_pids(UNIT(s));
101
102         if (state != old_state)
103                 log_debug("%s changed %s -> %s", UNIT(s)->id, scope_state_to_string(old_state), scope_state_to_string(state));
104
105         unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], true);
106 }
107
108 static int scope_add_default_dependencies(Scope *s) {
109         int r;
110
111         assert(s);
112
113         /* Make sure scopes are unloaded on shutdown */
114         r = unit_add_two_dependencies_by_name(
115                         UNIT(s),
116                         UNIT_BEFORE, UNIT_CONFLICTS,
117                         SPECIAL_SHUTDOWN_TARGET, NULL, true);
118         if (r < 0)
119                 return r;
120
121         return 0;
122 }
123
124 static int scope_verify(Scope *s) {
125         assert(s);
126
127         if (UNIT(s)->load_state != UNIT_LOADED)
128                 return 0;
129
130         if (set_isempty(UNIT(s)->pids) && UNIT(s)->manager->n_reloading <= 0) {
131                 log_error_unit(UNIT(s)->id, "Scope %s has no PIDs. Refusing.", UNIT(s)->id);
132                 return -EINVAL;
133         }
134
135         return 0;
136 }
137
138 static int scope_load(Unit *u) {
139         Scope *s = SCOPE(u);
140         int r;
141
142         assert(s);
143         assert(u->load_state == UNIT_STUB);
144
145         if (!u->transient && UNIT(s)->manager->n_reloading <= 0)
146                 return -ENOENT;
147
148         u->load_state = UNIT_LOADED;
149
150         r = unit_load_dropin(u);
151         if (r < 0)
152                 return r;
153
154         r = unit_patch_contexts(u);
155         if (r < 0)
156                 return r;
157
158         r = unit_add_default_slice(u, &s->cgroup_context);
159         if (r < 0)
160                 return r;
161
162         if (u->default_dependencies) {
163                 r = scope_add_default_dependencies(s);
164                 if (r < 0)
165                         return r;
166         }
167
168         return scope_verify(s);
169 }
170
171 static int scope_coldplug(Unit *u) {
172         Scope *s = SCOPE(u);
173         int r;
174
175         assert(s);
176         assert(s->state == SCOPE_DEAD);
177
178         if (s->deserialized_state != s->state) {
179
180                 if (IN_SET(s->deserialized_state, SCOPE_STOP_SIGKILL, SCOPE_STOP_SIGTERM)) {
181                         r = scope_arm_timer(s);
182                         if (r < 0)
183                                 return r;
184                 }
185
186                 if (!IN_SET(s->deserialized_state, SCOPE_DEAD, SCOPE_FAILED))
187                         unit_watch_all_pids(UNIT(s));
188
189                 scope_set_state(s, s->deserialized_state);
190         }
191
192         return 0;
193 }
194
195 static void scope_dump(Unit *u, FILE *f, const char *prefix) {
196         Scope *s = SCOPE(u);
197
198         assert(s);
199         assert(f);
200
201         fprintf(f,
202                 "%sScope State: %s\n"
203                 "%sResult: %s\n",
204                 prefix, scope_state_to_string(s->state),
205                 prefix, scope_result_to_string(s->result));
206
207         cgroup_context_dump(&s->cgroup_context, f, prefix);
208         kill_context_dump(&s->kill_context, f, prefix);
209 }
210
211 static void scope_enter_dead(Scope *s, ScopeResult f) {
212         assert(s);
213
214         if (f != SCOPE_SUCCESS)
215                 s->result = f;
216
217         scope_set_state(s, s->result != SCOPE_SUCCESS ? SCOPE_FAILED : SCOPE_DEAD);
218 }
219
220 static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) {
221         bool skip_signal = false;
222         int r;
223
224         assert(s);
225
226         if (f != SCOPE_SUCCESS)
227                 s->result = f;
228
229         unit_watch_all_pids(UNIT(s));
230
231         /* If we have a controller set let's ask the controller nicely
232          * to terminate the scope, instead of us going directly into
233          * SIGTERM beserk mode */
234         if (state == SCOPE_STOP_SIGTERM)
235                 skip_signal = bus_scope_send_request_stop(s) > 0;
236
237         if (!skip_signal) {
238                 r = unit_kill_context(
239                                 UNIT(s),
240                                 &s->kill_context,
241                                 state != SCOPE_STOP_SIGTERM,
242                                 -1, -1, false);
243                 if (r < 0)
244                         goto fail;
245         } else
246                 r = 1;
247
248         if (r > 0) {
249                 r = scope_arm_timer(s);
250                 if (r < 0)
251                         goto fail;
252
253                 scope_set_state(s, state);
254         } else if (state == SCOPE_STOP_SIGTERM)
255                 scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_SUCCESS);
256         else
257                 scope_enter_dead(s, SCOPE_SUCCESS);
258
259         return;
260
261 fail:
262         log_warning_unit(UNIT(s)->id,
263                          "%s failed to kill processes: %s", UNIT(s)->id, strerror(-r));
264
265         scope_enter_dead(s, SCOPE_FAILURE_RESOURCES);
266 }
267
268 static int scope_start(Unit *u) {
269         Scope *s = SCOPE(u);
270         int r;
271
272         assert(s);
273
274         if (s->state == SCOPE_FAILED)
275                 return -EPERM;
276
277         if (s->state == SCOPE_STOP_SIGTERM ||
278             s->state == SCOPE_STOP_SIGKILL)
279                 return -EAGAIN;
280
281         assert(s->state == SCOPE_DEAD);
282
283         if (!u->transient && UNIT(s)->manager->n_reloading <= 0)
284                 return -ENOENT;
285
286         r = unit_realize_cgroup(u);
287         if (r < 0) {
288                 log_error("Failed to realize cgroup: %s", strerror(-r));
289                 return r;
290         }
291
292         r = cg_attach_many_everywhere(u->manager->cgroup_supported, u->cgroup_path, UNIT(s)->pids);
293         if (r < 0)
294                 return r;
295
296         s->result = SCOPE_SUCCESS;
297
298         scope_set_state(s, SCOPE_RUNNING);
299         return 0;
300 }
301
302 static int scope_stop(Unit *u) {
303         Scope *s = SCOPE(u);
304
305         assert(s);
306
307         if (s->state == SCOPE_STOP_SIGTERM ||
308             s->state == SCOPE_STOP_SIGKILL)
309                 return 0;
310
311         assert(s->state == SCOPE_RUNNING ||
312                s->state == SCOPE_ABANDONED);
313
314         scope_enter_signal(s, SCOPE_STOP_SIGTERM, SCOPE_SUCCESS);
315         return 0;
316 }
317
318 static void scope_reset_failed(Unit *u) {
319         Scope *s = SCOPE(u);
320
321         assert(s);
322
323         if (s->state == SCOPE_FAILED)
324                 scope_set_state(s, SCOPE_DEAD);
325
326         s->result = SCOPE_SUCCESS;
327 }
328
329 static int scope_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
330         return unit_kill_common(u, who, signo, -1, -1, error);
331 }
332
333 static int scope_get_timeout(Unit *u, uint64_t *timeout) {
334         Scope *s = SCOPE(u);
335         int r;
336
337         if (!s->timer_event_source)
338                 return 0;
339
340         r = sd_event_source_get_time(s->timer_event_source, timeout);
341         if (r < 0)
342                 return r;
343
344         return 1;
345 }
346
347 static int scope_serialize(Unit *u, FILE *f, FDSet *fds) {
348         Scope *s = SCOPE(u);
349
350         assert(s);
351         assert(f);
352         assert(fds);
353
354         unit_serialize_item(u, f, "state", scope_state_to_string(s->state));
355         return 0;
356 }
357
358 static int scope_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
359         Scope *s = SCOPE(u);
360
361         assert(u);
362         assert(key);
363         assert(value);
364         assert(fds);
365
366         if (streq(key, "state")) {
367                 ScopeState state;
368
369                 state = scope_state_from_string(value);
370                 if (state < 0)
371                         log_debug("Failed to parse state value %s", value);
372                 else
373                         s->deserialized_state = state;
374
375         } else
376                 log_debug("Unknown serialization key '%s'", key);
377
378         return 0;
379 }
380
381 static bool scope_check_gc(Unit *u) {
382         Scope *s = SCOPE(u);
383         int r;
384
385         assert(s);
386
387         /* Never clean up scopes that still have a process around,
388          * even if the scope is formally dead. */
389
390         if (u->cgroup_path) {
391                 r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, true);
392                 if (r <= 0)
393                         return true;
394         }
395
396         return false;
397 }
398
399 static void scope_notify_cgroup_empty_event(Unit *u) {
400         Scope *s = SCOPE(u);
401         assert(u);
402
403         log_debug_unit(u->id, "%s: cgroup is empty", u->id);
404
405         if (IN_SET(s->state, SCOPE_RUNNING, SCOPE_ABANDONED, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL))
406                 scope_enter_dead(s, SCOPE_SUCCESS);
407 }
408
409 static void scope_sigchld_event(Unit *u, pid_t pid, int code, int status) {
410
411         /* If we get a SIGCHLD event for one of the processes we were
412            interested in, then we look for others to watch, under the
413            assumption that we'll sooner or later get a SIGCHLD for
414            them, as the original process we watched was probably the
415            parent of them, and they are hence now our children. */
416
417         unit_tidy_watch_pids(u, 0, 0);
418         unit_watch_all_pids(u);
419
420         /* If the PID set is empty now, then let's finish this off */
421         if (set_isempty(u->pids))
422                 scope_notify_cgroup_empty_event(u);
423 }
424
425 static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
426         Scope *s = SCOPE(userdata);
427
428         assert(s);
429         assert(s->timer_event_source == source);
430
431         switch (s->state) {
432
433         case SCOPE_STOP_SIGTERM:
434                 if (s->kill_context.send_sigkill) {
435                         log_warning_unit(UNIT(s)->id, "%s stopping timed out. Killing.", UNIT(s)->id);
436                         scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_FAILURE_TIMEOUT);
437                 } else {
438                         log_warning_unit(UNIT(s)->id, "%s stopping timed out. Skipping SIGKILL.", UNIT(s)->id);
439                         scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
440                 }
441
442                 break;
443
444         case SCOPE_STOP_SIGKILL:
445                 log_warning_unit(UNIT(s)->id, "%s still around after SIGKILL. Ignoring.", UNIT(s)->id);
446                 scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
447                 break;
448
449         default:
450                 assert_not_reached("Timeout at wrong time.");
451         }
452
453         return 0;
454 }
455
456 int scope_abandon(Scope *s) {
457         assert(s);
458
459         if (!IN_SET(s->state, SCOPE_RUNNING, SCOPE_ABANDONED))
460                 return -ESTALE;
461
462         free(s->controller);
463         s->controller = NULL;
464
465         /* The client is no longer watching the remaining processes,
466          * so let's step in here, under the assumption that the
467          * remaining processes will be sooner or later reassigned to
468          * us as parent. */
469
470         unit_tidy_watch_pids(UNIT(s), 0, 0);
471         unit_watch_all_pids(UNIT(s));
472
473         /* If the PID set is empty now, then let's finish this off */
474         if (set_isempty(UNIT(s)->pids))
475                 scope_notify_cgroup_empty_event(UNIT(s));
476         else
477                 scope_set_state(s, SCOPE_ABANDONED);
478
479         return 0;
480 }
481
482 _pure_ static UnitActiveState scope_active_state(Unit *u) {
483         assert(u);
484
485         return state_translation_table[SCOPE(u)->state];
486 }
487
488 _pure_ static const char *scope_sub_state_to_string(Unit *u) {
489         assert(u);
490
491         return scope_state_to_string(SCOPE(u)->state);
492 }
493
494 static const char* const scope_state_table[_SCOPE_STATE_MAX] = {
495         [SCOPE_DEAD] = "dead",
496         [SCOPE_RUNNING] = "running",
497         [SCOPE_ABANDONED] = "abandoned",
498         [SCOPE_STOP_SIGTERM] = "stop-sigterm",
499         [SCOPE_STOP_SIGKILL] = "stop-sigkill",
500         [SCOPE_FAILED] = "failed",
501 };
502
503 DEFINE_STRING_TABLE_LOOKUP(scope_state, ScopeState);
504
505 static const char* const scope_result_table[_SCOPE_RESULT_MAX] = {
506         [SCOPE_SUCCESS] = "success",
507         [SCOPE_FAILURE_RESOURCES] = "resources",
508         [SCOPE_FAILURE_TIMEOUT] = "timeout",
509 };
510
511 DEFINE_STRING_TABLE_LOOKUP(scope_result, ScopeResult);
512
513 const UnitVTable scope_vtable = {
514         .object_size = sizeof(Scope),
515         .cgroup_context_offset = offsetof(Scope, cgroup_context),
516         .kill_context_offset = offsetof(Scope, kill_context),
517
518         .sections =
519                 "Unit\0"
520                 "Scope\0"
521                 "Install\0",
522         .private_section = "Scope",
523
524         .no_alias = true,
525         .no_instances = true,
526
527         .init = scope_init,
528         .load = scope_load,
529         .done = scope_done,
530
531         .coldplug = scope_coldplug,
532
533         .dump = scope_dump,
534
535         .start = scope_start,
536         .stop = scope_stop,
537
538         .kill = scope_kill,
539
540         .get_timeout = scope_get_timeout,
541
542         .serialize = scope_serialize,
543         .deserialize_item = scope_deserialize_item,
544
545         .active_state = scope_active_state,
546         .sub_state_to_string = scope_sub_state_to_string,
547
548         .check_gc = scope_check_gc,
549
550         .sigchld_event = scope_sigchld_event,
551
552         .reset_failed = scope_reset_failed,
553
554         .notify_cgroup_empty = scope_notify_cgroup_empty_event,
555
556         .bus_interface = "org.freedesktop.systemd1.Scope",
557         .bus_vtable = bus_scope_vtable,
558         .bus_set_property = bus_scope_set_property,
559         .bus_commit_properties = bus_scope_commit_properties,
560
561         .can_transient = true
562 };