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