chiark / gitweb /
5beb4f80c427c65ed8d0588379ef92e34cceb5ed
[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 if (state == SCOPE_STOP_SIGTERM)
242                 scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_SUCCESS);
243         else
244                 scope_enter_dead(s, SCOPE_SUCCESS);
245
246         return;
247
248 fail:
249         log_warning_unit(UNIT(s)->id,
250                          "%s failed to kill processes: %s", UNIT(s)->id, strerror(-r));
251
252         scope_enter_dead(s, SCOPE_FAILURE_RESOURCES);
253 }
254
255 static int scope_start(Unit *u) {
256         Scope *s = SCOPE(u);
257         int r;
258
259         assert(s);
260
261         if (s->state == SCOPE_FAILED)
262                 return -EPERM;
263
264         if (s->state == SCOPE_STOP_SIGTERM ||
265             s->state == SCOPE_STOP_SIGKILL)
266                 return -EAGAIN;
267
268         assert(s->state == SCOPE_DEAD);
269
270         if (!u->transient && UNIT(s)->manager->n_reloading <= 0)
271                 return -ENOENT;
272
273         r = unit_realize_cgroup(u);
274         if (r < 0) {
275                 log_error("Failed to realize cgroup: %s", strerror(-r));
276                 return r;
277         }
278
279         r = cg_attach_many_everywhere(u->manager->cgroup_supported, u->cgroup_path, s->pids);
280         if (r < 0)
281                 return r;
282
283         set_free(s->pids);
284         s->pids = NULL;
285
286         s->result = SCOPE_SUCCESS;
287
288         scope_set_state(s, SCOPE_RUNNING);
289         return 0;
290 }
291
292 static int scope_stop(Unit *u) {
293         Scope *s = SCOPE(u);
294
295         assert(s);
296         assert(s->state == SCOPE_RUNNING);
297
298         if (s->state == SCOPE_STOP_SIGTERM ||
299             s->state == SCOPE_STOP_SIGKILL)
300                 return 0;
301
302         assert(s->state == SCOPE_RUNNING);
303
304         scope_enter_signal(s, SCOPE_STOP_SIGTERM, SCOPE_SUCCESS);
305         return 0;
306 }
307
308 static void scope_reset_failed(Unit *u) {
309         Scope *s = SCOPE(u);
310
311         assert(s);
312
313         if (s->state == SCOPE_FAILED)
314                 scope_set_state(s, SCOPE_DEAD);
315
316         s->result = SCOPE_SUCCESS;
317 }
318
319 static int scope_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
320         return unit_kill_common(u, who, signo, -1, -1, error);
321 }
322
323 static int scope_get_timeout(Unit *u, uint64_t *timeout) {
324         Scope *s = SCOPE(u);
325         int r;
326
327         if (!s->timer_event_source)
328                 return 0;
329
330         r = sd_event_source_get_time(s->timer_event_source, timeout);
331         if (r < 0)
332                 return r;
333
334         return 1;
335 }
336
337 static int scope_serialize(Unit *u, FILE *f, FDSet *fds) {
338         Scope *s = SCOPE(u);
339
340         assert(s);
341         assert(f);
342         assert(fds);
343
344         unit_serialize_item(u, f, "state", scope_state_to_string(s->state));
345         return 0;
346 }
347
348 static int scope_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
349         Scope *s = SCOPE(u);
350
351         assert(u);
352         assert(key);
353         assert(value);
354         assert(fds);
355
356         if (streq(key, "state")) {
357                 ScopeState state;
358
359                 state = scope_state_from_string(value);
360                 if (state < 0)
361                         log_debug("Failed to parse state value %s", value);
362                 else
363                         s->deserialized_state = state;
364
365         } else
366                 log_debug("Unknown serialization key '%s'", key);
367
368         return 0;
369 }
370
371 static bool scope_check_gc(Unit *u) {
372         Scope *s = SCOPE(u);
373         int r;
374
375         assert(s);
376
377         /* Never clean up scopes that still have a process around,
378          * even if the scope is formally dead. */
379
380         if (UNIT(s)->cgroup_path) {
381                 r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, UNIT(s)->cgroup_path, true);
382                 if (r <= 0)
383                         return true;
384         }
385
386         return false;
387 }
388
389 static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
390         Scope *s = SCOPE(userdata);
391
392         assert(s);
393         assert(s->timer_event_source == source);
394
395         switch (s->state) {
396
397         case SCOPE_STOP_SIGTERM:
398                 if (s->kill_context.send_sigkill) {
399                         log_warning_unit(UNIT(s)->id, "%s stopping timed out. Killing.", UNIT(s)->id);
400                         scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_FAILURE_TIMEOUT);
401                 } else {
402                         log_warning_unit(UNIT(s)->id, "%s stopping timed out. Skipping SIGKILL.", UNIT(s)->id);
403                         scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
404                 }
405
406                 break;
407
408         case SCOPE_STOP_SIGKILL:
409                 log_warning_unit(UNIT(s)->id, "%s still around after SIGKILL. Ignoring.", UNIT(s)->id);
410                 scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
411                 break;
412
413         default:
414                 assert_not_reached("Timeout at wrong time.");
415         }
416
417         return 0;
418 }
419
420 static void scope_notify_cgroup_empty_event(Unit *u) {
421         Scope *s = SCOPE(u);
422         assert(u);
423
424         log_debug_unit(u->id, "%s: cgroup is empty", u->id);
425
426         switch (s->state) {
427
428         case SCOPE_RUNNING:
429         case SCOPE_STOP_SIGTERM:
430         case SCOPE_STOP_SIGKILL:
431                 scope_enter_dead(s, SCOPE_SUCCESS);
432
433                 break;
434
435         default:
436                 ;
437         }
438 }
439
440 _pure_ static UnitActiveState scope_active_state(Unit *u) {
441         assert(u);
442
443         return state_translation_table[SCOPE(u)->state];
444 }
445
446 _pure_ static const char *scope_sub_state_to_string(Unit *u) {
447         assert(u);
448
449         return scope_state_to_string(SCOPE(u)->state);
450 }
451
452 static const char* const scope_state_table[_SCOPE_STATE_MAX] = {
453         [SCOPE_DEAD] = "dead",
454         [SCOPE_RUNNING] = "running",
455         [SCOPE_STOP_SIGTERM] = "stop-sigterm",
456         [SCOPE_STOP_SIGKILL] = "stop-sigkill",
457         [SCOPE_FAILED] = "failed",
458 };
459
460 DEFINE_STRING_TABLE_LOOKUP(scope_state, ScopeState);
461
462 static const char* const scope_result_table[_SCOPE_RESULT_MAX] = {
463         [SCOPE_SUCCESS] = "success",
464         [SCOPE_FAILURE_RESOURCES] = "resources",
465         [SCOPE_FAILURE_TIMEOUT] = "timeout",
466 };
467
468 DEFINE_STRING_TABLE_LOOKUP(scope_result, ScopeResult);
469
470 const UnitVTable scope_vtable = {
471         .object_size = sizeof(Scope),
472         .cgroup_context_offset = offsetof(Scope, cgroup_context),
473         .kill_context_offset = offsetof(Scope, kill_context),
474
475         .sections =
476                 "Unit\0"
477                 "Scope\0"
478                 "Install\0",
479         .private_section = "Scope",
480
481         .no_alias = true,
482         .no_instances = true,
483
484         .init = scope_init,
485         .load = scope_load,
486         .done = scope_done,
487
488         .coldplug = scope_coldplug,
489
490         .dump = scope_dump,
491
492         .start = scope_start,
493         .stop = scope_stop,
494
495         .kill = scope_kill,
496
497         .get_timeout = scope_get_timeout,
498
499         .serialize = scope_serialize,
500         .deserialize_item = scope_deserialize_item,
501
502         .active_state = scope_active_state,
503         .sub_state_to_string = scope_sub_state_to_string,
504
505         .check_gc = scope_check_gc,
506
507         .reset_failed = scope_reset_failed,
508
509         .notify_cgroup_empty = scope_notify_cgroup_empty_event,
510
511         .bus_interface = "org.freedesktop.systemd1.Scope",
512         .bus_vtable = bus_scope_vtable,
513         .bus_set_property = bus_scope_set_property,
514         .bus_commit_properties = bus_scope_commit_properties,
515
516         .can_transient = true
517 };