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