chiark / gitweb /
mount: don't fire PropertiesChanged signals for mounts that are stopped
[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         cgroup_context_init(&s->cgroup_context);
55         kill_context_init(&s->kill_context);
56
57         unit_cgroup_context_init_defaults(u, &s->cgroup_context);
58
59         UNIT(s)->ignore_on_isolate = true;
60         UNIT(s)->ignore_on_snapshot = true;
61 }
62
63 static void scope_done(Unit *u) {
64         Scope *s = SCOPE(u);
65
66         assert(u);
67
68         cgroup_context_done(&s->cgroup_context);
69
70         free(s->controller);
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, &s->timer_event_source, now(CLOCK_MONOTONIC) + s->timeout_stop_usec, 0, scope_dispatch_timer, s);
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 (!IN_SET(state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL))
104                 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
105
106         if (IN_SET(state, SCOPE_DEAD, SCOPE_FAILED))
107                 unit_unwatch_all_pids(UNIT(s));
108
109         if (state != old_state)
110                 log_debug("%s changed %s -> %s", UNIT(s)->id, scope_state_to_string(old_state), scope_state_to_string(state));
111
112         unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], true);
113 }
114
115 static int scope_add_default_dependencies(Scope *s) {
116         int r;
117
118         assert(s);
119
120         /* Make sure scopes are unloaded on shutdown */
121         r = unit_add_two_dependencies_by_name(
122                         UNIT(s),
123                         UNIT_BEFORE, UNIT_CONFLICTS,
124                         SPECIAL_SHUTDOWN_TARGET, NULL, true);
125         if (r < 0)
126                 return r;
127
128         return 0;
129 }
130
131 static int scope_verify(Scope *s) {
132         assert(s);
133
134         if (UNIT(s)->load_state != UNIT_LOADED)
135                 return 0;
136
137         if (set_isempty(UNIT(s)->pids) && UNIT(s)->manager->n_reloading <= 0) {
138                 log_error_unit(UNIT(s)->id, "Scope %s has no PIDs. Refusing.", UNIT(s)->id);
139                 return -EINVAL;
140         }
141
142         return 0;
143 }
144
145 static int scope_load(Unit *u) {
146         Scope *s = SCOPE(u);
147         int r;
148
149         assert(s);
150         assert(u->load_state == UNIT_STUB);
151
152         if (!u->transient && UNIT(s)->manager->n_reloading <= 0)
153                 return -ENOENT;
154
155         u->load_state = UNIT_LOADED;
156
157         r = unit_load_dropin(u);
158         if (r < 0)
159                 return r;
160
161         r = unit_add_default_slice(u);
162         if (r < 0)
163                 return r;
164
165         if (u->default_dependencies) {
166                 r = scope_add_default_dependencies(s);
167                 if (r < 0)
168                         return r;
169         }
170
171         return scope_verify(s);
172 }
173
174 static int scope_coldplug(Unit *u) {
175         Scope *s = SCOPE(u);
176         int r;
177
178         assert(s);
179         assert(s->state == SCOPE_DEAD);
180
181         if (s->deserialized_state != s->state) {
182
183                 if (IN_SET(s->deserialized_state, SCOPE_STOP_SIGKILL, SCOPE_STOP_SIGTERM)) {
184                         r = scope_arm_timer(s);
185                         if (r < 0)
186                                 return r;
187                 }
188
189                 if (!IN_SET(s->deserialized_state, SCOPE_DEAD, SCOPE_FAILED))
190                         unit_watch_all_pids(UNIT(s));
191
192                 scope_set_state(s, s->deserialized_state);
193         }
194
195         return 0;
196 }
197
198 static void scope_dump(Unit *u, FILE *f, const char *prefix) {
199         Scope *s = SCOPE(u);
200
201         assert(s);
202         assert(f);
203
204         fprintf(f,
205                 "%sScope State: %s\n"
206                 "%sResult: %s\n",
207                 prefix, scope_state_to_string(s->state),
208                 prefix, scope_result_to_string(s->result));
209
210         cgroup_context_dump(&s->cgroup_context, f, prefix);
211         kill_context_dump(&s->kill_context, f, prefix);
212 }
213
214 static void scope_enter_dead(Scope *s, ScopeResult f) {
215         assert(s);
216
217         if (f != SCOPE_SUCCESS)
218                 s->result = f;
219
220         scope_set_state(s, s->result != SCOPE_SUCCESS ? SCOPE_FAILED : SCOPE_DEAD);
221 }
222
223 static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) {
224         bool skip_signal = false;
225         int r;
226
227         assert(s);
228
229         if (f != SCOPE_SUCCESS)
230                 s->result = f;
231
232         unit_watch_all_pids(UNIT(s));
233
234         /* If we have a controller set let's ask the controller nicely
235          * to terminate the scope, instead of us going directly into
236          * SIGTERM beserk mode */
237         if (state == SCOPE_STOP_SIGTERM)
238                 skip_signal = bus_scope_send_request_stop(s) > 0;
239
240         if (!skip_signal) {
241                 r = unit_kill_context(
242                                 UNIT(s),
243                                 &s->kill_context,
244                                 state != SCOPE_STOP_SIGTERM,
245                                 -1, -1, false);
246                 if (r < 0)
247                         goto fail;
248         } else
249                 r = 1;
250
251         if (r > 0) {
252                 r = scope_arm_timer(s);
253                 if (r < 0)
254                         goto fail;
255
256                 scope_set_state(s, state);
257         } else if (state == SCOPE_STOP_SIGTERM)
258                 scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_SUCCESS);
259         else
260                 scope_enter_dead(s, SCOPE_SUCCESS);
261
262         return;
263
264 fail:
265         log_warning_unit(UNIT(s)->id,
266                          "%s failed to kill processes: %s", UNIT(s)->id, strerror(-r));
267
268         scope_enter_dead(s, SCOPE_FAILURE_RESOURCES);
269 }
270
271 static int scope_start(Unit *u) {
272         Scope *s = SCOPE(u);
273         int r;
274
275         assert(s);
276
277         if (s->state == SCOPE_FAILED)
278                 return -EPERM;
279
280         if (s->state == SCOPE_STOP_SIGTERM ||
281             s->state == SCOPE_STOP_SIGKILL)
282                 return -EAGAIN;
283
284         assert(s->state == SCOPE_DEAD);
285
286         if (!u->transient && UNIT(s)->manager->n_reloading <= 0)
287                 return -ENOENT;
288
289         r = unit_realize_cgroup(u);
290         if (r < 0) {
291                 log_error("Failed to realize cgroup: %s", strerror(-r));
292                 return r;
293         }
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_debug_unit(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_warning_unit(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_warning_unit(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_warning_unit(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 };