chiark / gitweb /
core: add support to run transient units in arbitrary slices
[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 void scope_init(Unit *u) {
44         Scope *s = SCOPE(u);
45
46         assert(u);
47         assert(u->load_state == UNIT_STUB);
48
49         s->timeout_stop_usec = DEFAULT_TIMEOUT_USEC;
50
51         watch_init(&s->timer_watch);
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         unit_unwatch_timer(u, &s->timer_watch);
71 }
72
73 static void scope_set_state(Scope *s, ScopeState state) {
74         ScopeState old_state;
75         assert(s);
76
77         old_state = s->state;
78         s->state = state;
79
80         if (state != SCOPE_STOP_SIGTERM &&
81             state != SCOPE_STOP_SIGKILL)
82                 unit_unwatch_timer(UNIT(s), &s->timer_watch);
83
84         if (state != old_state)
85                 log_debug("%s changed %s -> %s",
86                           UNIT(s)->id,
87                           scope_state_to_string(old_state),
88                           scope_state_to_string(state));
89
90         unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], true);
91 }
92
93 static int scope_add_default_dependencies(Scope *s) {
94         int r;
95
96         assert(s);
97
98         /* Make sure scopes are unloaded on shutdown */
99         r = unit_add_two_dependencies_by_name(
100                         UNIT(s),
101                         UNIT_BEFORE, UNIT_CONFLICTS,
102                         SPECIAL_SHUTDOWN_TARGET, NULL, true);
103         if (r < 0)
104                 return r;
105
106         return 0;
107 }
108
109 static int scope_verify(Scope *s) {
110         assert(s);
111
112         if (UNIT(s)->load_state != UNIT_LOADED)
113                 return 0;
114
115         if (set_size(s->pids) <= 0) {
116                 log_error_unit(UNIT(s)->id, "Scope %s has no PIDs. Refusing.", UNIT(s)->id);
117                 return -EINVAL;
118         }
119
120         return 0;
121 }
122
123 static int scope_load(Unit *u) {
124         Scope *s = SCOPE(u);
125         int r;
126
127         assert(s);
128         assert(u->load_state == UNIT_STUB);
129
130         if (!u->transient && UNIT(s)->manager->n_reloading <= 0)
131                 return -ENOENT;
132
133         u->load_state = UNIT_LOADED;
134
135         r = unit_load_dropin(u);
136         if (r < 0)
137                 return r;
138
139         r = unit_add_default_slice(u);
140         if (r < 0)
141                 return r;
142
143         if (u->default_dependencies) {
144                 r = scope_add_default_dependencies(s);
145                 if (r < 0)
146                         return r;
147         }
148
149         return scope_verify(s);
150 }
151
152 static int scope_coldplug(Unit *u) {
153         Scope *s = SCOPE(u);
154         int r;
155
156         assert(s);
157         assert(s->state == SCOPE_DEAD);
158
159         if (s->deserialized_state != s->state) {
160
161                 if ((s->deserialized_state == SCOPE_STOP_SIGKILL || s->deserialized_state == SCOPE_STOP_SIGTERM)
162                     && s->timeout_stop_usec > 0) {
163                         r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_stop_usec, &s->timer_watch);
164                         if (r < 0)
165
166                                 return r;
167                 }
168
169                 scope_set_state(s, s->deserialized_state);
170         }
171
172         return 0;
173 }
174
175 static void scope_dump(Unit *u, FILE *f, const char *prefix) {
176         Scope *s = SCOPE(u);
177
178         assert(s);
179         assert(f);
180
181         fprintf(f,
182                 "%sScope State: %s\n"
183                 "%sResult: %s\n",
184                 prefix, scope_state_to_string(s->state),
185                 prefix, scope_result_to_string(s->result));
186
187         cgroup_context_dump(&s->cgroup_context, f, prefix);
188         kill_context_dump(&s->kill_context, f, prefix);
189 }
190
191 static void scope_enter_dead(Scope *s, ScopeResult f) {
192         assert(s);
193
194         if (f != SCOPE_SUCCESS)
195                 s->result = f;
196
197         scope_set_state(s, s->result != SCOPE_SUCCESS ? SCOPE_FAILED : SCOPE_DEAD);
198 }
199
200 static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) {
201         int r;
202
203         assert(s);
204
205         if (f != SCOPE_SUCCESS)
206                 s->result = f;
207
208         r = unit_kill_context(
209                         UNIT(s),
210                         &s->kill_context,
211                         state != SCOPE_STOP_SIGTERM,
212                         -1, -1, false);
213         if (r < 0)
214                 goto fail;
215
216         if (r > 0) {
217                 if (s->timeout_stop_usec > 0) {
218                         r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_stop_usec, &s->timer_watch);
219                         if (r < 0)
220                                 goto fail;
221                 }
222
223                 scope_set_state(s, state);
224         } else
225                 scope_enter_dead(s, SCOPE_SUCCESS);
226
227         return;
228
229 fail:
230         log_warning_unit(UNIT(s)->id,
231                          "%s failed to kill processes: %s", UNIT(s)->id, strerror(-r));
232
233         scope_enter_dead(s, SCOPE_FAILURE_RESOURCES);
234 }
235
236 static int scope_start(Unit *u) {
237         Scope *s = SCOPE(u);
238         int r;
239
240         assert(s);
241
242         if (s->state == SCOPE_STOP_SIGTERM ||
243             s->state == SCOPE_STOP_SIGKILL)
244                 return -EAGAIN;
245
246         assert(s->state == SCOPE_DEAD);
247
248         if (!u->transient && UNIT(s)->manager->n_reloading <= 0)
249                 return -ENOENT;
250
251         r = unit_realize_cgroup(u);
252         if (r < 0) {
253                 log_error("Failed to realize cgroup: %s", strerror(-r));
254                 return r;
255         }
256
257         r = cg_attach_many_with_mask(u->cgroup_mask, u->cgroup_path, s->pids);
258         if (r < 0)
259                 return r;
260
261         set_free(s->pids);
262         s->pids = NULL;
263
264         s->result = SCOPE_SUCCESS;
265
266         scope_set_state(s, SCOPE_RUNNING);
267         return 0;
268 }
269
270 static int scope_stop(Unit *u) {
271         Scope *s = SCOPE(u);
272
273         assert(s);
274         assert(s->state == SCOPE_RUNNING);
275
276         if (s->state == SCOPE_STOP_SIGTERM ||
277             s->state == SCOPE_STOP_SIGKILL)
278                 return 0;
279
280         assert(s->state == SCOPE_RUNNING);
281
282         scope_enter_signal(s, SCOPE_STOP_SIGTERM, SCOPE_SUCCESS);
283         return 0;
284 }
285
286 static int scope_kill(Unit *u, KillWho who, int signo, DBusError *error) {
287         return unit_kill_common(u, who, signo, -1, -1, error);
288 }
289
290 static int scope_serialize(Unit *u, FILE *f, FDSet *fds) {
291         Scope *s = SCOPE(u);
292
293         assert(s);
294         assert(f);
295         assert(fds);
296
297         unit_serialize_item(u, f, "state", scope_state_to_string(s->state));
298         return 0;
299 }
300
301 static int scope_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
302         Scope *s = SCOPE(u);
303
304         assert(u);
305         assert(key);
306         assert(value);
307         assert(fds);
308
309         if (streq(key, "state")) {
310                 ScopeState state;
311
312                 state = scope_state_from_string(value);
313                 if (state < 0)
314                         log_debug("Failed to parse state value %s", value);
315                 else
316                         s->deserialized_state = state;
317
318         } else
319                 log_debug("Unknown serialization key '%s'", key);
320
321         return 0;
322 }
323
324 static bool scope_check_gc(Unit *u) {
325         Scope *s = SCOPE(u);
326         int r;
327
328         assert(s);
329
330         /* Never clean up scopes that still have a process around,
331          * even if the scope is formally dead. */
332
333         if (UNIT(s)->cgroup_path) {
334                 r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, UNIT(s)->cgroup_path, true);
335                 if (r <= 0)
336                         return true;
337         }
338
339         return false;
340 }
341
342 static void scope_timer_event(Unit *u, uint64_t elapsed, Watch*w) {
343         Scope *s = SCOPE(u);
344
345         assert(s);
346         assert(elapsed == 1);
347         assert(w == &s->timer_watch);
348
349         switch (s->state) {
350
351         case SCOPE_STOP_SIGTERM:
352                 if (s->kill_context.send_sigkill) {
353                         log_warning_unit(u->id, "%s stopping timed out. Killing.", u->id);
354                         scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_FAILURE_TIMEOUT);
355                 } else {
356                         log_warning_unit(u->id, "%s stopping timed out. Skipping SIGKILL.", u->id);
357                         scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
358                 }
359
360                 break;
361
362         case SCOPE_STOP_SIGKILL:
363                 log_warning_unit(u->id, "%s still around after SIGKILL. Ignoring.", u->id);
364                 scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
365                 break;
366
367         default:
368                 assert_not_reached("Timeout at wrong time.");
369         }
370 }
371
372 static void scope_notify_cgroup_empty_event(Unit *u) {
373         Scope *s = SCOPE(u);
374         assert(u);
375
376         log_debug_unit(u->id, "%s: cgroup is empty", u->id);
377
378         switch (s->state) {
379
380         case SCOPE_RUNNING:
381         case SCOPE_STOP_SIGTERM:
382         case SCOPE_STOP_SIGKILL:
383                 scope_enter_dead(s, SCOPE_SUCCESS);
384
385                 break;
386
387         default:
388                 ;
389         }
390 }
391
392 _pure_ static UnitActiveState scope_active_state(Unit *u) {
393         assert(u);
394
395         return state_translation_table[SCOPE(u)->state];
396 }
397
398 _pure_ static const char *scope_sub_state_to_string(Unit *u) {
399         assert(u);
400
401         return scope_state_to_string(SCOPE(u)->state);
402 }
403
404 static const char* const scope_state_table[_SCOPE_STATE_MAX] = {
405         [SCOPE_DEAD] = "dead",
406         [SCOPE_RUNNING] = "active",
407         [SCOPE_STOP_SIGTERM] = "stop-sigterm",
408         [SCOPE_STOP_SIGKILL] = "stop-sigkill",
409         [SCOPE_FAILED] = "failed",
410 };
411
412 DEFINE_STRING_TABLE_LOOKUP(scope_state, ScopeState);
413
414 static const char* const scope_result_table[_SCOPE_RESULT_MAX] = {
415         [SCOPE_SUCCESS] = "success",
416         [SCOPE_FAILURE_RESOURCES] = "resources",
417         [SCOPE_FAILURE_TIMEOUT] = "timeout",
418 };
419
420 DEFINE_STRING_TABLE_LOOKUP(scope_result, ScopeResult);
421
422 const UnitVTable scope_vtable = {
423         .object_size = sizeof(Scope),
424         .sections =
425                 "Unit\0"
426                 "Scope\0"
427                 "Install\0",
428
429         .private_section = "Scope",
430         .cgroup_context_offset = offsetof(Scope, cgroup_context),
431
432         .no_alias = true,
433         .no_instances = true,
434
435         .init = scope_init,
436         .load = scope_load,
437         .done = scope_done,
438
439         .coldplug = scope_coldplug,
440
441         .dump = scope_dump,
442
443         .start = scope_start,
444         .stop = scope_stop,
445
446         .kill = scope_kill,
447
448         .serialize = scope_serialize,
449         .deserialize_item = scope_deserialize_item,
450
451         .active_state = scope_active_state,
452         .sub_state_to_string = scope_sub_state_to_string,
453
454         .check_gc = scope_check_gc,
455
456         .timer_event = scope_timer_event,
457
458         .notify_cgroup_empty = scope_notify_cgroup_empty_event,
459
460         .bus_interface = "org.freedesktop.systemd1.Scope",
461         .bus_message_handler = bus_scope_message_handler,
462         .bus_set_property = bus_scope_set_property,
463         .bus_commit_properties = bus_scope_commit_properties,
464
465         .can_transient = true
466 };