busname.c revision 1c2e9646e4a1720fc8ad35c705c195ae1a2c5ce0
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering This file is part of systemd.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Copyright 2013 Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering systemd is free software; you can redistribute it and/or modify it
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering under the terms of the GNU Lesser General Public License as published by
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering (at your option) any later version.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering systemd is distributed in the hope that it will be useful, but
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Lesser General Public License for more details.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering You should have received a copy of the GNU Lesser General Public License
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poetteringstatic const UnitActiveState state_translation_table[_BUSNAME_STATE_MAX] = {
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poetteringstatic int busname_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int busname_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering n->timeout_usec = u->manager->default_timeout_start_usec;
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poetteringstatic void busname_unwatch_control_pid(BusName *n) {
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering unit_unwatch_pid(UNIT(n), n->control_pid);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void busname_free_policy(BusName *n) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering while ((p = n->policy)) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void busname_close_fd(BusName *n) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering n->starter_event_source = sd_event_source_unref(n->starter_event_source);
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek n->starter_fd = safe_close(n->starter_fd);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering n->timer_event_source = sd_event_source_unref(n->timer_event_source);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int busname_arm_timer(BusName *n) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering n->timer_event_source = sd_event_source_unref(n->timer_event_source);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = sd_event_source_set_time(n->timer_event_source, now(CLOCK_MONOTONIC) + n->timeout_usec);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek return sd_event_source_set_enabled(n->timer_event_source, SD_EVENT_ONESHOT);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering now(CLOCK_MONOTONIC) + n->timeout_usec, 0,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering (void) sd_event_source_set_description(n->timer_event_source, "busname-timer");
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmekstatic int busname_add_default_default_dependencies(BusName *n) {
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek r = unit_add_dependency_by_name(UNIT(n), UNIT_BEFORE, SPECIAL_BUSNAMES_TARGET, NULL, true);
4b8268f843b0da1cfe1995d93a0b1f95faccc454Zbigniew Jędrzejewski-Szmek if (UNIT(n)->manager->running_as == SYSTEMD_SYSTEM) {
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek r = unit_add_two_dependencies_by_name(UNIT(n), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek return unit_add_two_dependencies_by_name(UNIT(n), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmekstatic int busname_add_extras(BusName *n) {
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek n->name = unit_name_to_prefix(u->id);
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek r = unit_set_description(u, n->name);
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek r = unit_load_related_unit(u, ".service", &x);
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, UNIT_DEREF(n->service), true);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = busname_add_default_default_dependencies(n);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek if (!service_name_is_valid(n->name)) {
709f6e46a35ec492b70eb92943d82a8d838ce918Michal Schmidt log_unit_error(UNIT(n)->id, "%s's Name= setting is not a valid service name Refusing.", UNIT(n)->id);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_unit_error(UNIT(n)->id, "%s's Name= setting doesn't match unit name. Refusing.", UNIT(n)->id);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* This is a new unit? Then let's add in some extras */
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmekstatic void busname_dump(Unit *u, FILE *f, const char *prefix) {
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek "%sBus Name State: %s\n"
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek "%sResult: %s\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%sName: %s\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%sActivating: %s\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%sAccept FD: %s\n",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering prefix, busname_state_to_string(n->state),
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek prefix, busname_result_to_string(n->result),
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmekstatic void busname_unwatch_fd(BusName *n) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = sd_event_source_set_enabled(n->starter_event_source, SD_EVENT_OFF);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_unit_debug(UNIT(n)->id, "Failed to disable event source.");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = sd_event_source_set_enabled(n->starter_event_source, SD_EVENT_ON);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = sd_event_add_io(UNIT(n)->manager->event, &n->starter_event_source, n->starter_fd, EPOLLIN, busname_dispatch_io, n);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_unit_warning_errno(UNIT(n)->id, r, "Failed to watch starter fd: %m");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering (void) sd_event_source_set_description(n->starter_event_source, "busname-starter");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering mode = UNIT(n)->manager->running_as == SYSTEMD_SYSTEM ? "system" : "user";
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering n->starter_fd = bus_kernel_open_bus_fd(mode, &path);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return log_unit_warning_errno(UNIT(n)->id, n->starter_fd, "Failed to open %s: %m", path ?: "kdbus");
77ba8233f70719ddd53373f98c53c5cfd5ff13c7Michal Schmidtstatic void busname_set_state(BusName *n, BusNameState state) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (!IN_SET(state, BUSNAME_MAKING, BUSNAME_SIGTERM, BUSNAME_SIGKILL)) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek n->timer_event_source = sd_event_source_unref(n->timer_event_source);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek busname_unwatch_control_pid(n);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (!IN_SET(state, BUSNAME_LISTENING, BUSNAME_MAKING, BUSNAME_REGISTERED, BUSNAME_RUNNING))
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek log_unit_debug(UNIT(n)->id, "%s changed %s -> %s",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek UNIT(n)->id, busname_state_to_string(old_state), busname_state_to_string(state));
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek unit_notify(UNIT(n), state_translation_table[old_state], state_translation_table[state], true);
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmekstatic int busname_coldplug(Unit *u) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek assert(n->state == BUSNAME_DEAD);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (n->deserialized_state == n->state)
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (IN_SET(n->deserialized_state, BUSNAME_MAKING, BUSNAME_SIGTERM, BUSNAME_SIGKILL)) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek r = unit_watch_pid(UNIT(n), n->control_pid);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (IN_SET(n->deserialized_state, BUSNAME_MAKING, BUSNAME_LISTENING, BUSNAME_REGISTERED, BUSNAME_RUNNING)) {
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering if (n->deserialized_state == BUSNAME_LISTENING) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek busname_set_state(n, n->deserialized_state);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmekstatic int busname_make_starter(BusName *n, pid_t *_pid) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* We have to resolve the user/group names out-of-process,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * hence let's fork here. It's messy, but well, what can we
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering default_signals(SIGNALS_CRASH_HANDLER, SIGNALS_IGNORE, -1);
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt r = bus_kernel_make_starter(n->starter_fd, n->name, n->activating, n->accept_fd, n->policy, n->policy_world);
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek log_error_errno(r, "Failed to create starter connection at step %s: %m", exit_status_to_string(ret, EXIT_STATUS_SYSTEMD));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering n->timer_event_source = sd_event_source_unref(n->timer_event_source);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void busname_enter_dead(BusName *n, BusNameResult f) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering busname_set_state(n, n->result != BUSNAME_SUCCESS ? BUSNAME_FAILED : BUSNAME_DEAD);
7ff7394d9e4e9189c30fd018235e6b1728c6f2d0Zbigniew Jędrzejewski-Szmekstatic void busname_enter_signal(BusName *n, BusNameState state, BusNameResult f) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering state != BUSNAME_SIGTERM ? KILL_KILL : KILL_TERMINATE,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_unit_warning_errno(UNIT(n)->id, r, "%s failed to kill control process: %m", UNIT(n)->id);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_unit_warning_errno(UNIT(n)->id, r, "%s failed to arm timer: %m", UNIT(n)->id);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering busname_enter_signal(n, BUSNAME_SIGKILL, BUSNAME_SUCCESS);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void busname_enter_listening(BusName *n) {
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering log_unit_warning_errno(UNIT(n)->id, r, "%s failed to watch names: %m", UNIT(n)->id);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering busname_set_state(n, BUSNAME_REGISTERED);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering busname_enter_signal(n, BUSNAME_SIGTERM, BUSNAME_FAILURE_RESOURCES);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void busname_enter_making(BusName *n) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* If there is a policy, we need to resolve user/group
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * names, which we can't do from PID1, hence let's
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = busname_make_starter(n, &n->control_pid);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_unit_warning_errno(UNIT(n)->id, r, "%s failed to fork 'making' task: %m", UNIT(n)->id);
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering /* If there is no policy, we can do everything
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * directly from PID 1, hence do so. */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = bus_kernel_make_starter(n->starter_fd, n->name, n->activating, n->accept_fd, NULL, n->policy_world);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_unit_warning_errno(UNIT(n)->id, r, "%s failed to make starter: %m", UNIT(n)->id);
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void busname_enter_running(BusName *n) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* We don't take connections anymore if we are supposed to
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * shut down anyway */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_unit_debug(UNIT(n)->id, "Suppressing activation request on %s since unit stop is scheduled.", UNIT(n)->id);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Flush all queued activation reqeuest by closing and reopening the connection */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* If there's already a start pending don't bother to do
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering SET_FOREACH(other, UNIT(n)->dependencies[UNIT_TRIGGERS], i)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = manager_add_job(UNIT(n)->manager, JOB_START, UNIT_DEREF(n->service), JOB_REPLACE, true, &error, NULL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_unit_warning(UNIT(n)->id, "%s failed to queue service startup job: %s", UNIT(n)->id, bus_error_message(&error, r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* We cannot fulfill this request right now, try again later
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (IN_SET(n->state, BUSNAME_SIGTERM, BUSNAME_SIGKILL))
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Already on it! */
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek if (n->activating && UNIT_ISSET(n->service)) {
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek service = SERVICE(UNIT_DEREF(n->service));
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek if (UNIT(service)->load_state != UNIT_LOADED) {
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek log_unit_error(u->id, "Bus service %s not loaded, refusing.", UNIT(service)->id);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek assert(IN_SET(n->state, BUSNAME_DEAD, BUSNAME_FAILED));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Already on it */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (IN_SET(n->state, BUSNAME_SIGTERM, BUSNAME_SIGKILL))
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* If there's already something running, we go directly into
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * kill mode. */
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering busname_enter_signal(n, BUSNAME_SIGTERM, BUSNAME_SUCCESS);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(IN_SET(n->state, BUSNAME_REGISTERED, BUSNAME_LISTENING, BUSNAME_RUNNING));
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmekstatic int busname_serialize(Unit *u, FILE *f, FDSet *fds) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering unit_serialize_item(u, f, "state", busname_state_to_string(n->state));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering unit_serialize_item(u, f, "result", busname_result_to_string(n->result));
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek unit_serialize_item_format(u, f, "control-pid", PID_FMT, n->control_pid);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek copy = fdset_put_dup(fds, n->starter_fd);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek unit_serialize_item_format(u, f, "starter-fd", "%i", copy);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmekstatic int busname_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek state = busname_state_from_string(value);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek log_unit_debug(u->id, "Failed to parse state value %s", value);
else if (f != BUSNAME_SUCCESS)
n->result = f;
int fd;
assert(u);
assert(u);
struct kdbus_item *d;
struct kdbus_msg *k;
void *p = NULL;
assert(n);
return -errno;
if (p == MAP_FAILED) {
r = -errno;
goto finish;
switch (d->type) {
case KDBUS_ITEM_PIDS:
case KDBUS_ITEM_PID_COMM:
if (pid > 0)
log_unit_debug(UNIT(n)->id, "%s: Activation triggered by process " PID_FMT " (%s)", UNIT(n)->id, pid, strna(comm));
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)
static bool busname_supported(void) {
if (supported < 0)
return supported;
.sections =
.finished_start_job = {
.finished_stop_job = {