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