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