busname.c revision 4f10118016f9b2fd7e1d26c9ef7d91eb33fba694
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/>.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic const UnitActiveState state_translation_table[_BUSNAME_STATE_MAX] = {
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poetteringstatic int busname_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering n->event_source = sd_event_source_unref(n->event_source);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering n->starter_fd = safe_close(n->starter_fd);
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poetteringstatic int busname_add_default_default_dependencies(BusName *n) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = unit_add_dependency_by_name(UNIT(n), UNIT_BEFORE, SPECIAL_BUSNAMES_TARGET, NULL, true);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (UNIT(n)->manager->running_as == SYSTEMD_SYSTEM) {
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt r = unit_add_two_dependencies_by_name(UNIT(n), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return unit_add_two_dependencies_by_name(UNIT(n), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int busname_add_extras(BusName *n) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = unit_load_related_unit(u, ".service", &x);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, UNIT_DEREF(n->service), true);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek r = busname_add_default_default_dependencies(n);
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmekstatic int busname_verify(BusName *n) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error_unit(UNIT(n)->id, "%s's Name= setting is not a valid service name Refusing.", UNIT(n)->id);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek e = strappenda(n->name, ".busname");
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek if (!unit_has_name(UNIT(n), e)) {
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek log_error_unit(UNIT(n)->id, "%s's Name= setting doesn't match unit name. Refusing.", UNIT(n)->id);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmekstatic int busname_load(Unit *u) {
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek assert(u->load_state == UNIT_STUB);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek r = unit_load_fragment_and_dropin(u);
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek if (u->load_state == UNIT_LOADED) {
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek /* This is a new unit? Then let's add in some extras */
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmekstatic void busname_dump(Unit *u, FILE *f, const char *prefix) {
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek "%sBus Name State: %s\n"
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek "%sResult: %s\n"
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek "%sActivating: %s\n"
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek "%sAccept FD: %s\n",
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek prefix, busname_state_to_string(n->state),
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek prefix, busname_result_to_string(n->result),
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmekstatic void busname_unwatch_fd(BusName *n) {
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek r = sd_event_source_set_enabled(n->event_source, SD_EVENT_OFF);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_debug_unit(UNIT(n)->id, "Failed to disable event source.");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void busname_close_fd(BusName *n) {
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmekstatic int busname_watch_fd(BusName *n) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = sd_event_source_set_enabled(n->event_source, SD_EVENT_ON);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = sd_event_add_io(UNIT(n)->manager->event, &n->event_source, n->starter_fd, EPOLLIN, busname_dispatch_io, n);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning_unit(UNIT(n)->id, "Failed to watch starter fd: %s", strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering n->starter_fd = bus_kernel_create_starter(
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering UNIT(n)->manager->running_as == SYSTEMD_SYSTEM ? "system" : "user",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering n->name, n->activating, n->accept_fd, n->policy);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning_unit(UNIT(n)->id, "Failed to create starter fd: %s", strerror(-n->starter_fd));
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmekstatic void busname_set_state(BusName *n, BusNameState state) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!IN_SET(state, BUSNAME_LISTENING, BUSNAME_REGISTERED, BUSNAME_RUNNING))
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_debug_unit(UNIT(n)->id, "%s changed %s -> %s",
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek UNIT(n)->id, busname_state_to_string(old_state), busname_state_to_string(state));
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek unit_notify(UNIT(n), state_translation_table[old_state], state_translation_table[state], true);
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek assert(n->state == BUSNAME_DEAD);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (IN_SET(n->deserialized_state, BUSNAME_LISTENING, BUSNAME_REGISTERED, BUSNAME_RUNNING)) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (n->deserialized_state == BUSNAME_LISTENING) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering busname_set_state(n, n->deserialized_state);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void busname_enter_dead(BusName *n, BusNameResult f) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering busname_set_state(n, n->result != BUSNAME_SUCCESS ? BUSNAME_FAILED : BUSNAME_DEAD);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void busname_enter_listening(BusName *n) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning_unit(UNIT(n)->id, "%s failed to %s: %s", UNIT(n)->id,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering n->activating ? "listen on bus name" : "register policy for name",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek log_warning_unit(UNIT(n)->id, "%s failed to watch names: %s", UNIT(n)->id, strerror(-r));
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek busname_set_state(n, BUSNAME_LISTENING);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek busname_set_state(n, BUSNAME_REGISTERED);
eb56eb9b40950f1edcffdb7313f8de4f8572a6d5Michal Schmidt busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmekstatic void busname_enter_running(BusName *n) {
eb56eb9b40950f1edcffdb7313f8de4f8572a6d5Michal Schmidt _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek /* We don't take conenctions anymore if we are supposed to
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek * shut down anyway */
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (unit_stop_pending(UNIT(n))) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek log_debug_unit(UNIT(n)->id, "Suppressing activation request on %s since unit stop is scheduled.", UNIT(n)->id);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek /* Flush all queued activation reqeuest by closing and reopening the connection */
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek bus_kernel_drop_one(n->starter_fd);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek /* If there's already a start pending don't bother to do
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek SET_FOREACH(other, UNIT(n)->dependencies[UNIT_TRIGGERS], i)
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (unit_active_or_pending(other)) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek r = manager_add_job(UNIT(n)->manager, JOB_START, UNIT_DEREF(n->service), JOB_REPLACE, true, &error, NULL);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek busname_set_state(n, BUSNAME_RUNNING);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek log_warning_unit(UNIT(n)->id, "%s failed to queue service startup job: %s", UNIT(n)->id, bus_error_message(&error, r));
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (n->activating && UNIT_ISSET(n->service)) {
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek service = SERVICE(UNIT_DEREF(n->service));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (UNIT(service)->load_state != UNIT_LOADED) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error_unit(u->id, "Bus service %s not loaded, refusing.", UNIT(service)->id);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(IN_SET(n->state, BUSNAME_DEAD, BUSNAME_FAILED));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(IN_SET(n->state, BUSNAME_REGISTERED, BUSNAME_LISTENING, BUSNAME_RUNNING));
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek busname_enter_dead(n, BUSNAME_SUCCESS);
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmekstatic int busname_serialize(Unit *u, FILE *f, FDSet *fds) {
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek unit_serialize_item(u, f, "state", busname_state_to_string(n->state));
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek unit_serialize_item(u, f, "result", busname_result_to_string(n->result));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering copy = fdset_put_dup(fds, n->starter_fd);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering unit_serialize_item_format(u, f, "starter-fd", "%i", copy);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int busname_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek state = busname_state_from_string(value);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_debug_unit(u->id, "Failed to parse state value %s", value);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_debug_unit(u->id, "Failed to parse result value %s", value);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_debug_unit(u->id, "Failed to parse starter fd value %s", value);
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering log_debug_unit(u->id, "Unknown serialization key '%s'", key);
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering_pure_ static UnitActiveState busname_active_state(Unit *u) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return state_translation_table[BUSNAME(u)->state];
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering_pure_ static const char *busname_sub_state_to_string(Unit *u) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return busname_state_to_string(BUSNAME(u)->state);
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poetteringstatic int busname_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_debug_unit(UNIT(n)->id, "Activation request on %s", UNIT(n)->id);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error_unit(UNIT(n)->id, "%s: Got unexpected poll event (0x%x) on starter fd.",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void busname_reset_failed(Unit *u) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void busname_trigger_notify(Unit *u, Unit *other) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!IN_SET(n->state, BUSNAME_RUNNING, BUSNAME_LISTENING))
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (other->load_state != UNIT_LOADED || other->type != UNIT_SERVICE)
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering if (s->state == SERVICE_FAILED && s->result == SERVICE_FAILURE_START_LIMIT)
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering busname_enter_dead(n, BUSNAME_FAILURE_SERVICE_FAILED_PERMANENT);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering SERVICE_STOP, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic const char* const busname_state_table[_BUSNAME_STATE_MAX] = {
d4205751d4643c272059a3728045929dd0e5e800Lennart PoetteringDEFINE_STRING_TABLE_LOOKUP(busname_state, BusNameState);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic const char* const busname_result_table[_BUSNAME_RESULT_MAX] = {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering [BUSNAME_FAILURE_RESOURCES] = "resources",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering [BUSNAME_FAILURE_SERVICE_FAILED_PERMANENT] = "service-failed-permanent",
d4205751d4643c272059a3728045929dd0e5e800Lennart PoetteringDEFINE_STRING_TABLE_LOOKUP(busname_result, BusNameResult);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic const char* const busname_policy_access_table[_BUSNAME_POLICY_ACCESS_MAX] = {
d4205751d4643c272059a3728045929dd0e5e800Lennart PoetteringDEFINE_STRING_TABLE_LOOKUP(busname_policy_access, BusNamePolicyAccess);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering .deserialize_item = busname_deserialize_item,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering .sub_state_to_string = busname_sub_state_to_string,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering .trigger_notify = busname_trigger_notify,
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek .bus_interface = "org.freedesktop.systemd1.BusName",
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek .bus_vtable = bus_busname_vtable,
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek [JOB_DONE] = "Listening on %s.",
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek [JOB_FAILED] = "Failed to listen on %s.",
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek [JOB_DEPENDENCY] = "Dependency failed for %s.",
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek [JOB_TIMEOUT] = "Timed out starting %s.",
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek [JOB_FAILED] = "Failed stopping %s.",
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek [JOB_TIMEOUT] = "Timed out stopping %s.",