1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
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.
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.
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/>.
28 #include "load-fragment.h"
30 #include "dbus-scope.h"
32 #include "unit-name.h"
33 #include "load-dropin.h"
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
44 static int scope_dispatch_timer(sd_event_source
*source
, usec_t usec
, void *userdata
);
46 static void scope_init(Unit
*u
) {
50 assert(u
->load_state
== UNIT_STUB
);
52 s
->timeout_stop_usec
= u
->manager
->default_timeout_stop_usec
;
54 UNIT(s
)->ignore_on_isolate
= true;
55 UNIT(s
)->ignore_on_snapshot
= true;
58 static void scope_done(Unit
*u
) {
65 s
->timer_event_source
= sd_event_source_unref(s
->timer_event_source
);
68 static int scope_arm_timer(Scope
*s
) {
73 if (s
->timeout_stop_usec
<= 0) {
74 s
->timer_event_source
= sd_event_source_unref(s
->timer_event_source
);
78 if (s
->timer_event_source
) {
79 r
= sd_event_source_set_time(s
->timer_event_source
, now(CLOCK_MONOTONIC
) + s
->timeout_stop_usec
);
83 return sd_event_source_set_enabled(s
->timer_event_source
, SD_EVENT_ONESHOT
);
86 return sd_event_add_time(
87 UNIT(s
)->manager
->event
,
88 &s
->timer_event_source
,
90 now(CLOCK_MONOTONIC
) + s
->timeout_stop_usec
, 0,
91 scope_dispatch_timer
, s
);
94 static void scope_set_state(Scope
*s
, ScopeState state
) {
101 if (!IN_SET(state
, SCOPE_STOP_SIGTERM
, SCOPE_STOP_SIGKILL
))
102 s
->timer_event_source
= sd_event_source_unref(s
->timer_event_source
);
104 if (IN_SET(state
, SCOPE_DEAD
, SCOPE_FAILED
))
105 unit_unwatch_all_pids(UNIT(s
));
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
));
110 unit_notify(UNIT(s
), state_translation_table
[old_state
], state_translation_table
[state
], true);
113 static int scope_add_default_dependencies(Scope
*s
) {
118 /* Make sure scopes are unloaded on shutdown */
119 r
= unit_add_two_dependencies_by_name(
121 UNIT_BEFORE
, UNIT_CONFLICTS
,
122 SPECIAL_SHUTDOWN_TARGET
, NULL
, true);
129 static int scope_verify(Scope
*s
) {
132 if (UNIT(s
)->load_state
!= UNIT_LOADED
)
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
);
143 static int scope_load(Unit
*u
) {
148 assert(u
->load_state
== UNIT_STUB
);
150 if (!u
->transient
&& UNIT(s
)->manager
->n_reloading
<= 0)
153 u
->load_state
= UNIT_LOADED
;
155 r
= unit_load_dropin(u
);
159 r
= unit_patch_contexts(u
);
163 r
= unit_add_default_slice(u
, &s
->cgroup_context
);
167 if (u
->default_dependencies
) {
168 r
= scope_add_default_dependencies(s
);
173 return scope_verify(s
);
176 static int scope_coldplug(Unit
*u
) {
181 assert(s
->state
== SCOPE_DEAD
);
183 if (s
->deserialized_state
!= s
->state
) {
185 if (IN_SET(s
->deserialized_state
, SCOPE_STOP_SIGKILL
, SCOPE_STOP_SIGTERM
)) {
186 r
= scope_arm_timer(s
);
191 if (!IN_SET(s
->deserialized_state
, SCOPE_DEAD
, SCOPE_FAILED
))
192 unit_watch_all_pids(UNIT(s
));
194 scope_set_state(s
, s
->deserialized_state
);
200 static void scope_dump(Unit
*u
, FILE *f
, const char *prefix
) {
207 "%sScope State: %s\n"
209 prefix
, scope_state_to_string(s
->state
),
210 prefix
, scope_result_to_string(s
->result
));
212 cgroup_context_dump(&s
->cgroup_context
, f
, prefix
);
213 kill_context_dump(&s
->kill_context
, f
, prefix
);
216 static void scope_enter_dead(Scope
*s
, ScopeResult f
) {
219 if (f
!= SCOPE_SUCCESS
)
222 scope_set_state(s
, s
->result
!= SCOPE_SUCCESS
? SCOPE_FAILED
: SCOPE_DEAD
);
225 static void scope_enter_signal(Scope
*s
, ScopeState state
, ScopeResult f
) {
226 bool skip_signal
= false;
231 if (f
!= SCOPE_SUCCESS
)
234 unit_watch_all_pids(UNIT(s
));
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;
243 r
= unit_kill_context(
246 state
!= SCOPE_STOP_SIGTERM
? KILL_KILL
: KILL_TERMINATE
,
254 r
= scope_arm_timer(s
);
258 scope_set_state(s
, state
);
259 } else if (state
== SCOPE_STOP_SIGTERM
)
260 scope_enter_signal(s
, SCOPE_STOP_SIGKILL
, SCOPE_SUCCESS
);
262 scope_enter_dead(s
, SCOPE_SUCCESS
);
267 log_unit_warning(UNIT(s
)->id
,
268 "%s failed to kill processes: %s", UNIT(s
)->id
, strerror(-r
));
270 scope_enter_dead(s
, SCOPE_FAILURE_RESOURCES
);
273 static int scope_start(Unit
*u
) {
279 if (s
->state
== SCOPE_FAILED
)
282 if (s
->state
== SCOPE_STOP_SIGTERM
||
283 s
->state
== SCOPE_STOP_SIGKILL
)
286 assert(s
->state
== SCOPE_DEAD
);
288 if (!u
->transient
&& UNIT(s
)->manager
->n_reloading
<= 0)
291 r
= unit_attach_pids_to_cgroup(u
);
295 s
->result
= SCOPE_SUCCESS
;
297 scope_set_state(s
, SCOPE_RUNNING
);
301 static int scope_stop(Unit
*u
) {
306 if (s
->state
== SCOPE_STOP_SIGTERM
||
307 s
->state
== SCOPE_STOP_SIGKILL
)
310 assert(s
->state
== SCOPE_RUNNING
||
311 s
->state
== SCOPE_ABANDONED
);
313 scope_enter_signal(s
, SCOPE_STOP_SIGTERM
, SCOPE_SUCCESS
);
317 static void scope_reset_failed(Unit
*u
) {
322 if (s
->state
== SCOPE_FAILED
)
323 scope_set_state(s
, SCOPE_DEAD
);
325 s
->result
= SCOPE_SUCCESS
;
328 static int scope_kill(Unit
*u
, KillWho who
, int signo
, sd_bus_error
*error
) {
329 return unit_kill_common(u
, who
, signo
, -1, -1, error
);
332 static int scope_get_timeout(Unit
*u
, uint64_t *timeout
) {
336 if (!s
->timer_event_source
)
339 r
= sd_event_source_get_time(s
->timer_event_source
, timeout
);
346 static int scope_serialize(Unit
*u
, FILE *f
, FDSet
*fds
) {
353 unit_serialize_item(u
, f
, "state", scope_state_to_string(s
->state
));
357 static int scope_deserialize_item(Unit
*u
, const char *key
, const char *value
, FDSet
*fds
) {
365 if (streq(key
, "state")) {
368 state
= scope_state_from_string(value
);
370 log_debug("Failed to parse state value %s", value
);
372 s
->deserialized_state
= state
;
375 log_debug("Unknown serialization key '%s'", key
);
380 static bool scope_check_gc(Unit
*u
) {
383 /* Never clean up scopes that still have a process around,
384 * even if the scope is formally dead. */
386 if (u
->cgroup_path
) {
389 r
= cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER
, u
->cgroup_path
, true);
397 static void scope_notify_cgroup_empty_event(Unit
*u
) {
401 log_unit_debug(u
->id
, "%s: cgroup is empty", u
->id
);
403 if (IN_SET(s
->state
, SCOPE_RUNNING
, SCOPE_ABANDONED
, SCOPE_STOP_SIGTERM
, SCOPE_STOP_SIGKILL
))
404 scope_enter_dead(s
, SCOPE_SUCCESS
);
407 static void scope_sigchld_event(Unit
*u
, pid_t pid
, int code
, int status
) {
409 /* If we get a SIGCHLD event for one of the processes we were
410 interested in, then we look for others to watch, under the
411 assumption that we'll sooner or later get a SIGCHLD for
412 them, as the original process we watched was probably the
413 parent of them, and they are hence now our children. */
415 unit_tidy_watch_pids(u
, 0, 0);
416 unit_watch_all_pids(u
);
418 /* If the PID set is empty now, then let's finish this off */
419 if (set_isempty(u
->pids
))
420 scope_notify_cgroup_empty_event(u
);
423 static int scope_dispatch_timer(sd_event_source
*source
, usec_t usec
, void *userdata
) {
424 Scope
*s
= SCOPE(userdata
);
427 assert(s
->timer_event_source
== source
);
431 case SCOPE_STOP_SIGTERM
:
432 if (s
->kill_context
.send_sigkill
) {
433 log_unit_warning(UNIT(s
)->id
, "%s stopping timed out. Killing.", UNIT(s
)->id
);
434 scope_enter_signal(s
, SCOPE_STOP_SIGKILL
, SCOPE_FAILURE_TIMEOUT
);
436 log_unit_warning(UNIT(s
)->id
, "%s stopping timed out. Skipping SIGKILL.", UNIT(s
)->id
);
437 scope_enter_dead(s
, SCOPE_FAILURE_TIMEOUT
);
442 case SCOPE_STOP_SIGKILL
:
443 log_unit_warning(UNIT(s
)->id
, "%s still around after SIGKILL. Ignoring.", UNIT(s
)->id
);
444 scope_enter_dead(s
, SCOPE_FAILURE_TIMEOUT
);
448 assert_not_reached("Timeout at wrong time.");
454 int scope_abandon(Scope
*s
) {
457 if (!IN_SET(s
->state
, SCOPE_RUNNING
, SCOPE_ABANDONED
))
461 s
->controller
= NULL
;
463 /* The client is no longer watching the remaining processes,
464 * so let's step in here, under the assumption that the
465 * remaining processes will be sooner or later reassigned to
468 unit_tidy_watch_pids(UNIT(s
), 0, 0);
469 unit_watch_all_pids(UNIT(s
));
471 /* If the PID set is empty now, then let's finish this off */
472 if (set_isempty(UNIT(s
)->pids
))
473 scope_notify_cgroup_empty_event(UNIT(s
));
475 scope_set_state(s
, SCOPE_ABANDONED
);
480 _pure_
static UnitActiveState
scope_active_state(Unit
*u
) {
483 return state_translation_table
[SCOPE(u
)->state
];
486 _pure_
static const char *scope_sub_state_to_string(Unit
*u
) {
489 return scope_state_to_string(SCOPE(u
)->state
);
492 static const char* const scope_state_table
[_SCOPE_STATE_MAX
] = {
493 [SCOPE_DEAD
] = "dead",
494 [SCOPE_RUNNING
] = "running",
495 [SCOPE_ABANDONED
] = "abandoned",
496 [SCOPE_STOP_SIGTERM
] = "stop-sigterm",
497 [SCOPE_STOP_SIGKILL
] = "stop-sigkill",
498 [SCOPE_FAILED
] = "failed",
501 DEFINE_STRING_TABLE_LOOKUP(scope_state
, ScopeState
);
503 static const char* const scope_result_table
[_SCOPE_RESULT_MAX
] = {
504 [SCOPE_SUCCESS
] = "success",
505 [SCOPE_FAILURE_RESOURCES
] = "resources",
506 [SCOPE_FAILURE_TIMEOUT
] = "timeout",
509 DEFINE_STRING_TABLE_LOOKUP(scope_result
, ScopeResult
);
511 const UnitVTable scope_vtable
= {
512 .object_size
= sizeof(Scope
),
513 .cgroup_context_offset
= offsetof(Scope
, cgroup_context
),
514 .kill_context_offset
= offsetof(Scope
, kill_context
),
520 .private_section
= "Scope",
523 .no_instances
= true,
529 .coldplug
= scope_coldplug
,
533 .start
= scope_start
,
538 .get_timeout
= scope_get_timeout
,
540 .serialize
= scope_serialize
,
541 .deserialize_item
= scope_deserialize_item
,
543 .active_state
= scope_active_state
,
544 .sub_state_to_string
= scope_sub_state_to_string
,
546 .check_gc
= scope_check_gc
,
548 .sigchld_event
= scope_sigchld_event
,
550 .reset_failed
= scope_reset_failed
,
552 .notify_cgroup_empty
= scope_notify_cgroup_empty_event
,
554 .bus_interface
= "org.freedesktop.systemd1.Scope",
555 .bus_vtable
= bus_scope_vtable
,
556 .bus_set_property
= bus_scope_set_property
,
557 .bus_commit_properties
= bus_scope_commit_properties
,
559 .can_transient
= true