busname.c revision db2cb23b5b179707000d28a11efb3d888d06ee80
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering This file is part of systemd.
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering Copyright 2013 Lennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering systemd is free software; you can redistribute it and/or modify it
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering under the terms of the GNU Lesser General Public License as published by
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering (at your option) any later version.
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering systemd is distributed in the hope that it will be useful, but
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering Lesser General Public License for more details.
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering You should have received a copy of the GNU Lesser General Public License
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poetteringstatic const UnitActiveState state_translation_table[_BUSNAME_STATE_MAX] = {
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen [BUSNAME_DEAD] = UNIT_INACTIVE,
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen [BUSNAME_MAKING] = UNIT_ACTIVATING,
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen [BUSNAME_REGISTERED] = UNIT_ACTIVE,
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poetteringstatic int busname_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poetteringstatic int busname_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering n->timeout_usec = u->manager->default_timeout_start_usec;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poetteringstatic void busname_unwatch_control_pid(BusName *n) {
46e65dcc3a522b5e992e165b5e61d14254026859Lennart Poettering unit_unwatch_pid(UNIT(n), n->control_pid);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poetteringstatic void busname_free_policy(BusName *n) {
2f6a59070559786428d9eaf199ae3d61772b2225Kay Sievers while ((p = n->policy)) {
2311eb2ff0c3ff80ec3645b02c97170c9a565454Kay Sievers n->starter_event_source = sd_event_source_unref(n->starter_event_source);
9ff09bcb86fb125768667aca9bc0b10b1745370aShawn Landden n->timer_event_source = sd_event_source_unref(n->timer_event_source);
2f6a59070559786428d9eaf199ae3d61772b2225Kay Sievers n->timer_event_source = sd_event_source_unref(n->timer_event_source);
2311eb2ff0c3ff80ec3645b02c97170c9a565454Kay Sievers r = sd_event_source_set_time(n->timer_event_source, now(CLOCK_MONOTONIC) + n->timeout_usec);
9ff09bcb86fb125768667aca9bc0b10b1745370aShawn Landden return sd_event_source_set_enabled(n->timer_event_source, SD_EVENT_ONESHOT);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poetteringstatic int busname_add_default_default_dependencies(BusName *n) {
9ff09bcb86fb125768667aca9bc0b10b1745370aShawn Landden r = unit_add_dependency_by_name(UNIT(n), UNIT_BEFORE, SPECIAL_BUSNAMES_TARGET, NULL, true);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering if (UNIT(n)->manager->running_as == SYSTEMD_SYSTEM) {
2f6a59070559786428d9eaf199ae3d61772b2225Kay Sievers r = unit_add_two_dependencies_by_name(UNIT(n), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true);
7f35b7bc4a241e9aa3b1512fd345cbf5b2e5a782Kay Sievers return unit_add_two_dependencies_by_name(UNIT(n), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
2af32104c47dadf426f2e7697cd7382520476fc5Lennart Poettering r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, UNIT_DEREF(n->service), true);
f18ca9dcdeda247e208f7143e834fd2fb2070d80Kay Sievers r = busname_add_default_default_dependencies(n);
9ff09bcb86fb125768667aca9bc0b10b1745370aShawn Landden log_error_unit(UNIT(n)->id, "%s's Name= setting is not a valid service name Refusing.", UNIT(n)->id);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering log_error_unit(UNIT(n)->id, "%s's Name= setting doesn't match unit name. Refusing.", UNIT(n)->id);
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen if (u->load_state == UNIT_LOADED) {
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /* This is a new unit? Then let's add in some extras */
adacb9575a09981fcf11279f2f661e3fc21e58ffLennart Poetteringstatic void busname_dump(Unit *u, FILE *f, const char *prefix) {
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering "%sBus Name State: %s\n"
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering "%sResult: %s\n"
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen "%sActivating: %s\n"
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen "%sAccept FD: %s\n",
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering prefix, busname_state_to_string(n->state),
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering prefix, busname_result_to_string(n->result),
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poetteringstatic void busname_unwatch_fd(BusName *n) {
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen if (!n->starter_event_source)
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen r = sd_event_source_set_enabled(n->starter_event_source, SD_EVENT_OFF);
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen log_debug_unit(UNIT(n)->id, "Failed to disable event source.");
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersenstatic int busname_watch_fd(BusName *n) {
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering r = sd_event_source_set_enabled(n->starter_event_source, SD_EVENT_ON);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering r = sd_event_add_io(UNIT(n)->manager->event, &n->starter_event_source, n->starter_fd, EPOLLIN, busname_dispatch_io, n);
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen log_warning_unit(UNIT(n)->id, "Failed to watch starter fd: %s", strerror(-r));
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersenstatic int busname_open_fd(BusName *n) {
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen _cleanup_free_ char *path = NULL;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering mode = UNIT(n)->manager->running_as == SYSTEMD_SYSTEM ? "system" : "user";
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering n->starter_fd = bus_kernel_open_bus_fd(mode, &path);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering log_warning_unit(UNIT(n)->id, "Failed to open %s: %s",
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering path ?: "kdbus", strerror(-n->starter_fd));
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersenstatic void busname_set_state(BusName *n, BusNameState state) {
e5609878d8802e2469c433be418bcbcf55fbe63bLennart Poettering if (!IN_SET(state, BUSNAME_MAKING, BUSNAME_SIGTERM, BUSNAME_SIGKILL)) {
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen n->timer_event_source = sd_event_source_unref(n->timer_event_source);
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen busname_unwatch_control_pid(n);
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen if (!IN_SET(state, BUSNAME_LISTENING, BUSNAME_MAKING, BUSNAME_REGISTERED, BUSNAME_RUNNING))
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering log_debug_unit(UNIT(n)->id, "%s changed %s -> %s",
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering UNIT(n)->id, busname_state_to_string(old_state), busname_state_to_string(state));
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering unit_notify(UNIT(n), state_translation_table[old_state], state_translation_table[state], true);
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen assert(n->state == BUSNAME_DEAD);
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen if (n->deserialized_state == n->state)
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen if (IN_SET(n->deserialized_state, BUSNAME_MAKING, BUSNAME_SIGTERM, BUSNAME_SIGKILL)) {
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen r = unit_watch_pid(UNIT(n), n->control_pid);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering if (IN_SET(n->deserialized_state, BUSNAME_MAKING, BUSNAME_LISTENING, BUSNAME_REGISTERED, BUSNAME_RUNNING)) {
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering if (n->deserialized_state == BUSNAME_LISTENING) {
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering busname_set_state(n, n->deserialized_state);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poetteringstatic int busname_make_starter(BusName *n, pid_t *_pid) {
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /* We have to resolve the user/group names out-of-process,
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering * hence let's fork here. It's messy, but well, what can we
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering default_signals(SIGNALS_CRASH_HANDLER, SIGNALS_IGNORE, -1);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering r = bus_kernel_make_starter(n->starter_fd, n->name, n->activating, n->accept_fd, n->policy, n->policy_world);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering log_error("Failed to create starter connection at step %s: %s", exit_status_to_string(ret, EXIT_STATUS_SYSTEMD), strerror(-r));
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering n->timer_event_source = sd_event_source_unref(n->timer_event_source);
7591abd48079edc1f2adbd922e4b83eb73abeabeLennart Poetteringstatic void busname_enter_dead(BusName *n, BusNameResult f) {
4f8f66cb4236783cd3cbee97fefc9aaa8469ac08Zbigniew Jędrzejewski-Szmek busname_set_state(n, n->result != BUSNAME_SUCCESS ? BUSNAME_FAILED : BUSNAME_DEAD);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poetteringstatic void busname_enter_signal(BusName *n, BusNameState state, BusNameResult f) {
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering state != BUSNAME_SIGTERM ? KILL_KILL : KILL_TERMINATE,
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering log_warning_unit(UNIT(n)->id, "%s failed to kill control process: %s", UNIT(n)->id, strerror(-r));
c978343015c787713651dff571acb5207367f5f2Lennart Poettering log_warning_unit(UNIT(n)->id, "%s failed to arm timer: %s", UNIT(n)->id, strerror(-r));
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering busname_enter_signal(n, BUSNAME_SIGKILL, BUSNAME_SUCCESS);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poetteringstatic void busname_enter_listening(BusName *n) {
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen log_warning_unit(UNIT(n)->id, "%s failed to watch names: %s", UNIT(n)->id, strerror(-r));
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen busname_set_state(n, BUSNAME_REGISTERED);
546158bc6f46f8004cc11e81d19d223e0da56730Jan Janssen busname_enter_signal(n, BUSNAME_SIGTERM, BUSNAME_FAILURE_RESOURCES);
c978343015c787713651dff571acb5207367f5f2Lennart Poetteringstatic void busname_enter_making(BusName *n) {
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /* If there is a policy, we need to resolve user/group
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering * names, which we can't do from PID1, hence let's
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering r = busname_make_starter(n, &n->control_pid);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering log_warning_unit(UNIT(n)->id, "%s failed to fork 'making' task: %s", UNIT(n)->id, strerror(-r));
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /* If there is no policy, we can do everything
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering * directly from PID 1, hence do so. */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering r = bus_kernel_make_starter(n->starter_fd, n->name, n->activating, n->accept_fd, NULL, n->policy_world);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering log_warning_unit(UNIT(n)->id, "%s failed to make starter: %s", UNIT(n)->id, strerror(-r));
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poetteringstatic void busname_enter_running(BusName *n) {
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /* We don't take conenctions anymore if we are supposed to
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering * shut down anyway */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering log_debug_unit(UNIT(n)->id, "Suppressing activation request on %s since unit stop is scheduled.", UNIT(n)->id);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /* Flush all queued activation reqeuest by closing and reopening the connection */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /* If there's already a start pending don't bother to do
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering SET_FOREACH(other, UNIT(n)->dependencies[UNIT_TRIGGERS], i)
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering r = manager_add_job(UNIT(n)->manager, JOB_START, UNIT_DEREF(n->service), JOB_REPLACE, true, &error, NULL);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering log_warning_unit(UNIT(n)->id, "%s failed to queue service startup job: %s", UNIT(n)->id, bus_error_message(&error, r));
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /* We cannot fulfill this request right now, try again later
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering if (IN_SET(n->state, BUSNAME_SIGTERM, BUSNAME_SIGKILL))
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering /* Already on it! */
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering if (n->activating && UNIT_ISSET(n->service)) {
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering service = SERVICE(UNIT_DEREF(n->service));
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering if (UNIT(service)->load_state != UNIT_LOADED) {
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering log_error_unit(u->id, "Bus service %s not loaded, refusing.", UNIT(service)->id);
a281d9c7851b16c4c9195d042901540ee9ced799Thomas Hindoe Paaboel Andersen assert(IN_SET(n->state, BUSNAME_DEAD, BUSNAME_FAILED));
assert(n);
return -EAGAIN;
assert(n);
assert(f);
if (n->control_pid > 0)
if (n->starter_fd >= 0) {
int copy;
if (copy < 0)
return copy;
assert(n);
if (state < 0)
else if (f != BUSNAME_SUCCESS)
n->result = f;
int fd;
assert(u);
assert(u);
assert(n);
goto fail;
fail:
assert(n);
n->control_pid = 0;
f = BUSNAME_SUCCESS;
if (f != BUSNAME_SUCCESS)
n->result = f;
switch (n->state) {
case BUSNAME_MAKING:
if (f == BUSNAME_SUCCESS)
case BUSNAME_SIGTERM:
case BUSNAME_SIGKILL:
busname_enter_dead(n, f);
assert(n);
switch (n->state) {
case BUSNAME_MAKING:
case BUSNAME_SIGTERM:
case BUSNAME_SIGKILL:
assert(n);
Service *s;
assert(n);
if (!n->timer_event_source)
.sections =
.finished_start_job = {
.finished_stop_job = {