]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/scope.c
core: unified cgroup hierarchy support
[thirdparty/systemd.git] / src / core / scope.c
CommitLineData
6c12b52e
LP
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>
6c12b52e
LP
23#include <unistd.h>
24
6c12b52e 25#include "log.h"
efdb0237 26#include "strv.h"
6c12b52e
LP
27#include "special.h"
28#include "unit-name.h"
efdb0237
LP
29#include "unit.h"
30#include "scope.h"
31#include "dbus-scope.h"
6c12b52e
LP
32#include "load-dropin.h"
33
34static const UnitActiveState state_translation_table[_SCOPE_STATE_MAX] = {
35 [SCOPE_DEAD] = UNIT_INACTIVE,
36 [SCOPE_RUNNING] = UNIT_ACTIVE,
a911bb9a 37 [SCOPE_ABANDONED] = UNIT_ACTIVE,
6c12b52e
LP
38 [SCOPE_STOP_SIGTERM] = UNIT_DEACTIVATING,
39 [SCOPE_STOP_SIGKILL] = UNIT_DEACTIVATING,
40 [SCOPE_FAILED] = UNIT_FAILED
41};
42
718db961
LP
43static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
44
6c12b52e
LP
45static void scope_init(Unit *u) {
46 Scope *s = SCOPE(u);
47
48 assert(u);
49 assert(u->load_state == UNIT_STUB);
50
1f19a534 51 s->timeout_stop_usec = u->manager->default_timeout_stop_usec;
6c12b52e 52
6c12b52e
LP
53 UNIT(s)->ignore_on_isolate = true;
54 UNIT(s)->ignore_on_snapshot = true;
55}
56
57static void scope_done(Unit *u) {
58 Scope *s = SCOPE(u);
59
60 assert(u);
61
2d4a39e7
LP
62 free(s->controller);
63
718db961
LP
64 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
65}
66
67static int scope_arm_timer(Scope *s) {
68 int r;
69
70 assert(s);
71
72 if (s->timeout_stop_usec <= 0) {
73 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
74 return 0;
75 }
76
77 if (s->timer_event_source) {
78 r = sd_event_source_set_time(s->timer_event_source, now(CLOCK_MONOTONIC) + s->timeout_stop_usec);
79 if (r < 0)
80 return r;
81
82 return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
83 }
84
cbf60d0a 85 r = sd_event_add_time(
6a0f1f6d
LP
86 UNIT(s)->manager->event,
87 &s->timer_event_source,
88 CLOCK_MONOTONIC,
89 now(CLOCK_MONOTONIC) + s->timeout_stop_usec, 0,
90 scope_dispatch_timer, s);
7dfbe2e3
TG
91 if (r < 0)
92 return r;
93
94 (void) sd_event_source_set_description(s->timer_event_source, "scope-timer");
95
96 return 0;
6c12b52e
LP
97}
98
99static void scope_set_state(Scope *s, ScopeState state) {
100 ScopeState old_state;
101 assert(s);
102
103 old_state = s->state;
104 s->state = state;
105
a911bb9a 106 if (!IN_SET(state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL))
718db961 107 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
6c12b52e 108
a911bb9a
LP
109 if (IN_SET(state, SCOPE_DEAD, SCOPE_FAILED))
110 unit_unwatch_all_pids(UNIT(s));
111
6c12b52e 112 if (state != old_state)
a911bb9a 113 log_debug("%s changed %s -> %s", UNIT(s)->id, scope_state_to_string(old_state), scope_state_to_string(state));
6c12b52e
LP
114
115 unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], true);
116}
117
118static int scope_add_default_dependencies(Scope *s) {
119 int r;
120
121 assert(s);
122
123 /* Make sure scopes are unloaded on shutdown */
124 r = unit_add_two_dependencies_by_name(
125 UNIT(s),
126 UNIT_BEFORE, UNIT_CONFLICTS,
127 SPECIAL_SHUTDOWN_TARGET, NULL, true);
128 if (r < 0)
129 return r;
130
131 return 0;
132}
133
134static int scope_verify(Scope *s) {
135 assert(s);
136
137 if (UNIT(s)->load_state != UNIT_LOADED)
138 return 0;
139
efdb0237
LP
140 if (set_isempty(UNIT(s)->pids) &&
141 !manager_is_reloading_or_reexecuting(UNIT(s)->manager) <= 0 &&
142 !unit_has_name(UNIT(s), SPECIAL_INIT_SCOPE)) {
f2341e0a 143 log_unit_error(UNIT(s), "Scope has no PIDs. Refusing.");
6c12b52e
LP
144 return -EINVAL;
145 }
146
147 return 0;
148}
149
150static int scope_load(Unit *u) {
151 Scope *s = SCOPE(u);
152 int r;
153
154 assert(s);
155 assert(u->load_state == UNIT_STUB);
156
efdb0237 157 if (!u->transient && !manager_is_reloading_or_reexecuting(u->manager))
6c12b52e
LP
158 return -ENOENT;
159
160 u->load_state = UNIT_LOADED;
161
162 r = unit_load_dropin(u);
163 if (r < 0)
164 return r;
165
598459ce
LP
166 r = unit_patch_contexts(u);
167 if (r < 0)
168 return r;
169
d79200e2 170 r = unit_set_default_slice(u);
6c12b52e
LP
171 if (r < 0)
172 return r;
173
174 if (u->default_dependencies) {
175 r = scope_add_default_dependencies(s);
176 if (r < 0)
177 return r;
178 }
179
180 return scope_verify(s);
181}
182
be847e82 183static int scope_coldplug(Unit *u) {
6c12b52e
LP
184 Scope *s = SCOPE(u);
185 int r;
186
187 assert(s);
188 assert(s->state == SCOPE_DEAD);
189
190 if (s->deserialized_state != s->state) {
191
a911bb9a 192 if (IN_SET(s->deserialized_state, SCOPE_STOP_SIGKILL, SCOPE_STOP_SIGTERM)) {
718db961 193 r = scope_arm_timer(s);
6c12b52e 194 if (r < 0)
6c12b52e
LP
195 return r;
196 }
197
a911bb9a
LP
198 if (!IN_SET(s->deserialized_state, SCOPE_DEAD, SCOPE_FAILED))
199 unit_watch_all_pids(UNIT(s));
200
6c12b52e
LP
201 scope_set_state(s, s->deserialized_state);
202 }
203
204 return 0;
205}
206
207static void scope_dump(Unit *u, FILE *f, const char *prefix) {
208 Scope *s = SCOPE(u);
209
210 assert(s);
211 assert(f);
212
213 fprintf(f,
214 "%sScope State: %s\n"
215 "%sResult: %s\n",
216 prefix, scope_state_to_string(s->state),
217 prefix, scope_result_to_string(s->result));
218
219 cgroup_context_dump(&s->cgroup_context, f, prefix);
220 kill_context_dump(&s->kill_context, f, prefix);
221}
222
223static void scope_enter_dead(Scope *s, ScopeResult f) {
224 assert(s);
225
226 if (f != SCOPE_SUCCESS)
227 s->result = f;
228
229 scope_set_state(s, s->result != SCOPE_SUCCESS ? SCOPE_FAILED : SCOPE_DEAD);
230}
231
232static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) {
2d4a39e7 233 bool skip_signal = false;
6c12b52e
LP
234 int r;
235
236 assert(s);
237
238 if (f != SCOPE_SUCCESS)
239 s->result = f;
240
a911bb9a
LP
241 unit_watch_all_pids(UNIT(s));
242
2d4a39e7
LP
243 /* If we have a controller set let's ask the controller nicely
244 * to terminate the scope, instead of us going directly into
245 * SIGTERM beserk mode */
246 if (state == SCOPE_STOP_SIGTERM)
247 skip_signal = bus_scope_send_request_stop(s) > 0;
248
249 if (!skip_signal) {
250 r = unit_kill_context(
251 UNIT(s),
252 &s->kill_context,
db2cb23b 253 state != SCOPE_STOP_SIGTERM ? KILL_KILL : KILL_TERMINATE,
2d4a39e7
LP
254 -1, -1, false);
255 if (r < 0)
256 goto fail;
257 } else
258 r = 1;
6c12b52e
LP
259
260 if (r > 0) {
718db961
LP
261 r = scope_arm_timer(s);
262 if (r < 0)
263 goto fail;
6c12b52e
LP
264
265 scope_set_state(s, state);
ac84d1fb
LP
266 } else if (state == SCOPE_STOP_SIGTERM)
267 scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_SUCCESS);
268 else
6c12b52e
LP
269 scope_enter_dead(s, SCOPE_SUCCESS);
270
271 return;
272
273fail:
f2341e0a 274 log_unit_warning_errno(UNIT(s), r, "Failed to kill processes: %m");
6c12b52e
LP
275
276 scope_enter_dead(s, SCOPE_FAILURE_RESOURCES);
277}
278
279static int scope_start(Unit *u) {
280 Scope *s = SCOPE(u);
281 int r;
282
283 assert(s);
284
efdb0237
LP
285 if (unit_has_name(u, SPECIAL_INIT_SCOPE))
286 return -EPERM;
287
7b617155
LP
288 if (s->state == SCOPE_FAILED)
289 return -EPERM;
290
dd305ec9 291 /* We can't fulfill this right now, please try again later */
6c12b52e
LP
292 if (s->state == SCOPE_STOP_SIGTERM ||
293 s->state == SCOPE_STOP_SIGKILL)
294 return -EAGAIN;
295
296 assert(s->state == SCOPE_DEAD);
297
efdb0237 298 if (!u->transient && !manager_is_reloading_or_reexecuting(u->manager))
6c12b52e
LP
299 return -ENOENT;
300
5ad096b3
LP
301 (void) unit_realize_cgroup(u);
302 (void) unit_reset_cpu_usage(u);
303
7b3fd631 304 r = unit_attach_pids_to_cgroup(u);
dd305ec9 305 if (r < 0) {
f2341e0a 306 log_unit_warning_errno(UNIT(s), r, "Failed to add PIDs to scope's control group: %m");
68a01fb6 307 scope_enter_dead(s, SCOPE_FAILURE_RESOURCES);
6c12b52e 308 return r;
dd305ec9 309 }
6c12b52e 310
6c12b52e
LP
311 s->result = SCOPE_SUCCESS;
312
313 scope_set_state(s, SCOPE_RUNNING);
82a2b6bb 314 return 1;
6c12b52e
LP
315}
316
317static int scope_stop(Unit *u) {
318 Scope *s = SCOPE(u);
319
320 assert(s);
6c12b52e
LP
321
322 if (s->state == SCOPE_STOP_SIGTERM ||
323 s->state == SCOPE_STOP_SIGKILL)
324 return 0;
325
a911bb9a
LP
326 assert(s->state == SCOPE_RUNNING ||
327 s->state == SCOPE_ABANDONED);
6c12b52e
LP
328
329 scope_enter_signal(s, SCOPE_STOP_SIGTERM, SCOPE_SUCCESS);
82a2b6bb 330 return 1;
6c12b52e
LP
331}
332
8bcca7e2
LP
333static void scope_reset_failed(Unit *u) {
334 Scope *s = SCOPE(u);
335
336 assert(s);
337
338 if (s->state == SCOPE_FAILED)
339 scope_set_state(s, SCOPE_DEAD);
340
341 s->result = SCOPE_SUCCESS;
342}
343
718db961 344static int scope_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
6c12b52e
LP
345 return unit_kill_common(u, who, signo, -1, -1, error);
346}
347
68db7a3b
ZJS
348static int scope_get_timeout(Unit *u, uint64_t *timeout) {
349 Scope *s = SCOPE(u);
350 int r;
351
352 if (!s->timer_event_source)
353 return 0;
354
355 r = sd_event_source_get_time(s->timer_event_source, timeout);
356 if (r < 0)
357 return r;
358
359 return 1;
360}
361
6c12b52e
LP
362static int scope_serialize(Unit *u, FILE *f, FDSet *fds) {
363 Scope *s = SCOPE(u);
364
365 assert(s);
366 assert(f);
367 assert(fds);
368
369 unit_serialize_item(u, f, "state", scope_state_to_string(s->state));
370 return 0;
371}
372
373static int scope_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
374 Scope *s = SCOPE(u);
375
376 assert(u);
377 assert(key);
378 assert(value);
379 assert(fds);
380
381 if (streq(key, "state")) {
382 ScopeState state;
383
384 state = scope_state_from_string(value);
385 if (state < 0)
f2341e0a 386 log_unit_debug(u, "Failed to parse state value: %s", value);
6c12b52e
LP
387 else
388 s->deserialized_state = state;
389
390 } else
f2341e0a 391 log_unit_debug(u, "Unknown serialization key: %s", key);
6c12b52e
LP
392
393 return 0;
394}
395
396static bool scope_check_gc(Unit *u) {
4e2744fc 397 assert(u);
6c12b52e
LP
398
399 /* Never clean up scopes that still have a process around,
400 * even if the scope is formally dead. */
401
a911bb9a 402 if (u->cgroup_path) {
4e2744fc
RC
403 int r;
404
6f883237 405 r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path);
6c12b52e
LP
406 if (r <= 0)
407 return true;
408 }
409
410 return false;
411}
412
a911bb9a
LP
413static void scope_notify_cgroup_empty_event(Unit *u) {
414 Scope *s = SCOPE(u);
415 assert(u);
416
f2341e0a 417 log_unit_debug(u, "cgroup is empty");
a911bb9a
LP
418
419 if (IN_SET(s->state, SCOPE_RUNNING, SCOPE_ABANDONED, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL))
420 scope_enter_dead(s, SCOPE_SUCCESS);
421}
422
423static void scope_sigchld_event(Unit *u, pid_t pid, int code, int status) {
424
425 /* If we get a SIGCHLD event for one of the processes we were
426 interested in, then we look for others to watch, under the
427 assumption that we'll sooner or later get a SIGCHLD for
428 them, as the original process we watched was probably the
429 parent of them, and they are hence now our children. */
430
431 unit_tidy_watch_pids(u, 0, 0);
432 unit_watch_all_pids(u);
433
434 /* If the PID set is empty now, then let's finish this off */
435 if (set_isempty(u->pids))
436 scope_notify_cgroup_empty_event(u);
437}
438
718db961
LP
439static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
440 Scope *s = SCOPE(userdata);
6c12b52e
LP
441
442 assert(s);
718db961 443 assert(s->timer_event_source == source);
6c12b52e
LP
444
445 switch (s->state) {
446
447 case SCOPE_STOP_SIGTERM:
448 if (s->kill_context.send_sigkill) {
f2341e0a 449 log_unit_warning(UNIT(s), "Stopping timed out. Killing.");
6c12b52e
LP
450 scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_FAILURE_TIMEOUT);
451 } else {
f2341e0a 452 log_unit_warning(UNIT(s), "Stopping timed out. Skipping SIGKILL.");
6c12b52e
LP
453 scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
454 }
455
456 break;
457
458 case SCOPE_STOP_SIGKILL:
f2341e0a 459 log_unit_warning(UNIT(s), "Still around after SIGKILL. Ignoring.");
6c12b52e
LP
460 scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
461 break;
462
463 default:
464 assert_not_reached("Timeout at wrong time.");
465 }
718db961
LP
466
467 return 0;
6c12b52e
LP
468}
469
a911bb9a
LP
470int scope_abandon(Scope *s) {
471 assert(s);
6c12b52e 472
efdb0237
LP
473 if (unit_has_name(UNIT(s), SPECIAL_INIT_SCOPE))
474 return -EPERM;
475
a911bb9a
LP
476 if (!IN_SET(s->state, SCOPE_RUNNING, SCOPE_ABANDONED))
477 return -ESTALE;
6c12b52e 478
a911bb9a
LP
479 free(s->controller);
480 s->controller = NULL;
6c12b52e 481
a911bb9a
LP
482 /* The client is no longer watching the remaining processes,
483 * so let's step in here, under the assumption that the
484 * remaining processes will be sooner or later reassigned to
485 * us as parent. */
6c12b52e 486
a911bb9a
LP
487 unit_tidy_watch_pids(UNIT(s), 0, 0);
488 unit_watch_all_pids(UNIT(s));
6c12b52e 489
a911bb9a
LP
490 /* If the PID set is empty now, then let's finish this off */
491 if (set_isempty(UNIT(s)->pids))
492 scope_notify_cgroup_empty_event(UNIT(s));
493 else
494 scope_set_state(s, SCOPE_ABANDONED);
495
496 return 0;
6c12b52e
LP
497}
498
499_pure_ static UnitActiveState scope_active_state(Unit *u) {
500 assert(u);
501
502 return state_translation_table[SCOPE(u)->state];
503}
504
505_pure_ static const char *scope_sub_state_to_string(Unit *u) {
506 assert(u);
507
508 return scope_state_to_string(SCOPE(u)->state);
509}
510
efdb0237
LP
511static int scope_enumerate(Manager *m) {
512 Unit *u;
513 int r;
514
515 assert(m);
516
517 /* Let's unconditionally add the "init.scope" special unit
518 * that encapsulates PID 1. Note that PID 1 already is in the
519 * cgroup for this, we hence just need to allocate the object
520 * for it and that's it. */
521
522 u = manager_get_unit(m, SPECIAL_INIT_SCOPE);
523 if (!u) {
524 u = unit_new(m, sizeof(Scope));
525 if (!u)
526 return log_oom();
527
528 r = unit_add_name(u, SPECIAL_INIT_SCOPE);
529 if (r < 0) {
530 unit_free(u);
531 return log_error_errno(r, "Failed to add init.scope name");
532 }
533 }
534
535 u->transient = true;
536 u->default_dependencies = false;
537 u->no_gc = true;
538 SCOPE(u)->deserialized_state = SCOPE_RUNNING;
539 SCOPE(u)->kill_context.kill_signal = SIGRTMIN+14;
540
541 /* Prettify things, if we can. */
542 if (!u->description)
543 u->description = strdup("System and Service Manager");
544 if (!u->documentation)
545 (void) strv_extend(&u->documentation, "man:systemd(1)");
546
547 unit_add_to_load_queue(u);
548 unit_add_to_dbus_queue(u);
549
550 return 0;
551}
552
6c12b52e
LP
553static const char* const scope_state_table[_SCOPE_STATE_MAX] = {
554 [SCOPE_DEAD] = "dead",
358712f3 555 [SCOPE_RUNNING] = "running",
a911bb9a 556 [SCOPE_ABANDONED] = "abandoned",
6c12b52e
LP
557 [SCOPE_STOP_SIGTERM] = "stop-sigterm",
558 [SCOPE_STOP_SIGKILL] = "stop-sigkill",
559 [SCOPE_FAILED] = "failed",
560};
561
562DEFINE_STRING_TABLE_LOOKUP(scope_state, ScopeState);
563
564static const char* const scope_result_table[_SCOPE_RESULT_MAX] = {
565 [SCOPE_SUCCESS] = "success",
566 [SCOPE_FAILURE_RESOURCES] = "resources",
567 [SCOPE_FAILURE_TIMEOUT] = "timeout",
568};
569
570DEFINE_STRING_TABLE_LOOKUP(scope_result, ScopeResult);
571
572const UnitVTable scope_vtable = {
573 .object_size = sizeof(Scope),
718db961
LP
574 .cgroup_context_offset = offsetof(Scope, cgroup_context),
575 .kill_context_offset = offsetof(Scope, kill_context),
576
6c12b52e
LP
577 .sections =
578 "Unit\0"
579 "Scope\0"
580 "Install\0",
6c12b52e 581 .private_section = "Scope",
6c12b52e
LP
582
583 .no_alias = true,
584 .no_instances = true,
585
586 .init = scope_init,
587 .load = scope_load,
588 .done = scope_done,
589
590 .coldplug = scope_coldplug,
591
592 .dump = scope_dump,
593
594 .start = scope_start,
595 .stop = scope_stop,
596
597 .kill = scope_kill,
598
68db7a3b
ZJS
599 .get_timeout = scope_get_timeout,
600
6c12b52e
LP
601 .serialize = scope_serialize,
602 .deserialize_item = scope_deserialize_item,
603
604 .active_state = scope_active_state,
605 .sub_state_to_string = scope_sub_state_to_string,
606
607 .check_gc = scope_check_gc,
608
a911bb9a
LP
609 .sigchld_event = scope_sigchld_event,
610
8bcca7e2
LP
611 .reset_failed = scope_reset_failed,
612
6c12b52e
LP
613 .notify_cgroup_empty = scope_notify_cgroup_empty_event,
614
718db961 615 .bus_vtable = bus_scope_vtable,
6c12b52e
LP
616 .bus_set_property = bus_scope_set_property,
617 .bus_commit_properties = bus_scope_commit_properties,
618
efdb0237
LP
619 .can_transient = true,
620
621 .enumerate = scope_enumerate,
6c12b52e 622};