busname.c revision 6bf0f408e4833152197fb38fb10a9989c89f3a59
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack This file is part of systemd.
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack Copyright 2013 Lennart Poettering
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack systemd is free software; you can redistribute it and/or modify it
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack under the terms of the GNU Lesser General Public License as published by
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack the Free Software Foundation; either version 2.1 of the License, or
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack (at your option) any later version.
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack systemd is distributed in the hope that it will be useful, but
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack WITHOUT ANY WARRANTY; without even the implied warranty of
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack Lesser General Public License for more details.
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack You should have received a copy of the GNU Lesser General Public License
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack along with systemd; If not, see <http://www.gnu.org/licenses/>.
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mackstatic const UnitActiveState state_translation_table[_BUSNAME_STATE_MAX] = {
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mackstatic int busname_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mackstatic int busname_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack n->timeout_usec = u->manager->default_timeout_start_usec;
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mackstatic void busname_unwatch_control_pid(BusName *n) {
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack while ((p = n->policy)) {
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack n->starter_event_source = sd_event_source_unref(n->starter_event_source);
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack n->timer_event_source = sd_event_source_unref(n->timer_event_source);
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mackstatic int busname_arm_timer(BusName *n, usec_t usec) {
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack r = sd_event_source_set_time(n->timer_event_source, usec);
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack return sd_event_source_set_enabled(n->timer_event_source, SD_EVENT_ONESHOT);
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack (void) sd_event_source_set_description(n->timer_event_source, "busname-timer");
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mackstatic int busname_add_default_default_dependencies(BusName *n) {
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack r = unit_add_dependency_by_name(UNIT(n), UNIT_BEFORE, SPECIAL_BUSNAMES_TARGET, NULL, true);
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack if (UNIT(n)->manager->running_as == MANAGER_SYSTEM) {
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack r = unit_add_two_dependencies_by_name(UNIT(n), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true);
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack return unit_add_two_dependencies_by_name(UNIT(n), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
if (u->default_dependencies) {
assert(n);
return -EINVAL;
return -EINVAL;
assert(u);
r = unit_load_fragment_and_dropin(u);
r = busname_add_extras(n);
return busname_verify(n);
assert(n);
assert(f);
fprintf(f,
if (n->control_pid > 0)
fprintf(f,
assert(n);
if (!n->starter_event_source)
assert(n);
if (n->starter_fd < 0)
if (n->starter_event_source) {
goto fail;
r = sd_event_add_io(UNIT(n)->manager->event, &n->starter_event_source, n->starter_fd, EPOLLIN, busname_dispatch_io, n);
goto fail;
fail:
const char *mode;
assert(n);
if (n->starter_fd >= 0)
if (n->starter_fd < 0)
assert(n);
busname_close_fd(n);
log_unit_debug(UNIT(n), "Changed %s -> %s", busname_state_to_string(old_state), busname_state_to_string(state));
assert(n);
if (n->control_pid > 0 &&
if (IN_SET(n->deserialized_state, BUSNAME_MAKING, BUSNAME_LISTENING, BUSNAME_REGISTERED, BUSNAME_RUNNING)) {
r = busname_open_fd(n);
r = busname_watch_fd(n);
goto fail;
if (pid < 0)
return -errno;
if (pid == 0) {
int ret;
r = bus_kernel_make_starter(n->starter_fd, n->name, n->activating, n->accept_fd, n->policy, n->policy_world);
goto fail_child;
_exit(0);
log_open();
log_error_errno(r, "Failed to create starter connection at step %s: %m", exit_status_to_string(ret, EXIT_STATUS_SYSTEMD));
goto fail;
fail:
assert(n);
if (f != BUSNAME_SUCCESS)
n->result = f;
assert(n);
if (f != BUSNAME_SUCCESS)
n->result = f;
n->control_pid,
goto fail;
goto fail;
fail:
assert(n);
if (n->activating) {
r = busname_watch_fd(n);
goto fail;
fail:
assert(n);
r = busname_open_fd(n);
goto fail;
if (n->policy) {
goto fail;
r = bus_kernel_make_starter(n->starter_fd, n->name, n->activating, n->accept_fd, NULL, n->policy_world);
goto fail;
fail:
bool pending = false;
Iterator i;
assert(n);
if (!n->activating)
pending = true;
if (!pending) {
r = -ENOENT;
goto fail;
r = manager_add_job(UNIT(n)->manager, JOB_START, UNIT_DEREF(n->service), JOB_REPLACE, &error, NULL);
goto fail;
fail:
assert(n);
return -EAGAIN;
return -ENOENT;
assert(n);
return -EAGAIN;
assert(n);
assert(f);
if (n->control_pid > 0)
assert(n);
if (state < 0)
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);
if (p == MAP_FAILED) {
goto finish;
switch (d->type) {
case KDBUS_ITEM_PIDS:
case KDBUS_ITEM_PID_COMM:
if (pid > 0)
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);
assert(n);
usec_t t;
if (!n->timer_event_source)
if (t == USEC_INFINITY)
*timeout = t;
static bool busname_supported(void) {
if (supported < 0)
return supported;
.sections =
.no_alias = true,
.no_instances = true,
.finished_start_job = {
.finished_stop_job = {