busname.c revision ff975efb2e88dcd5221a2f0d76c4c87e85b821a8
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt This file is part of systemd.
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt Copyright 2013 Lennart Poettering
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt systemd is free software; you can redistribute it and/or modify it
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt under the terms of the GNU Lesser General Public License as published by
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt the Free Software Foundation; either version 2.1 of the License, or
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt (at your option) any later version.
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt systemd is distributed in the hope that it will be useful, but
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt WITHOUT ANY WARRANTY; without even the implied warranty of
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt Lesser General Public License for more details.
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt You should have received a copy of the GNU Lesser General Public License
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt along with systemd; If not, see <http://www.gnu.org/licenses/>.
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flyktstatic const UnitActiveState state_translation_table[_BUSNAME_STATE_MAX] = {
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flyktstatic int busname_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt n->event_source = sd_event_source_unref(n->event_source);
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt if (n->starter_fd >= 0) {
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flyktstatic int busname_add_default_default_dependencies(BusName *n) {
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt r = unit_add_dependency_by_name(UNIT(n), UNIT_BEFORE, SPECIAL_BUSNAMES_TARGET, NULL, true);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt if (UNIT(n)->manager->running_as == SYSTEMD_SYSTEM) {
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt r = unit_add_two_dependencies_by_name(UNIT(n), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true);
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt return unit_add_two_dependencies_by_name(UNIT(n), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, UNIT_DEREF(n->service), true);
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt r = busname_add_default_default_dependencies(n);
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt log_error_unit(UNIT(n)->id, "%s's Name= setting is not a valid service name Refusing.", UNIT(n)->id);
f12ed3bf0b315fc88d5fbdf5bdca14b218c86e0cPatrik Flykt log_error_unit(UNIT(n)->id, "%s's Name= setting doesn't match unit name. Refusing.", UNIT(n)->id);
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt /* This is a new unit? Then let's add in some extras */
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flyktstatic void busname_dump(Unit *u, FILE *f, const char *prefix) {
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt "%sBus Name State: %s\n"
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt "%sResult: %s\n"
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt "%sName: %s\n",
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt r = sd_event_source_set_enabled(n->event_source, SD_EVENT_OFF);
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt log_debug_unit(UNIT(n)->id, "Failed to disable event source.");
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt r = sd_event_source_set_enabled(n->event_source, SD_EVENT_ON);
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt r = sd_event_add_io(UNIT(n)->manager->event, n->starter_fd, EPOLLIN, busname_dispatch_io, n, &n->event_source);
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt if (r < 0) {
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt log_warning_unit(UNIT(n)->id, "Failed to watch starter fd: %s", strerror(-r));
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt n->starter_fd = bus_kernel_create_starter(UNIT(n)->manager->running_as == SYSTEMD_SYSTEM ? "system" : "user", n->name);
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt log_warning_unit(UNIT(n)->id, "Failed to create starter fd: %s", strerror(-n->starter_fd));
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flyktstatic void busname_set_state(BusName *n, BusNameState state) {
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt if (!IN_SET(state, BUSNAME_LISTENING, BUSNAME_RUNNING))
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt log_debug_unit(UNIT(n)->id, "%s changed %s -> %s",
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt UNIT(n)->id, busname_state_to_string(old_state), busname_state_to_string(state));
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt unit_notify(UNIT(n), state_translation_table[old_state], state_translation_table[state], true);
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt if (IN_SET(n->deserialized_state, BUSNAME_LISTENING, BUSNAME_RUNNING)) {
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt if (n->deserialized_state == BUSNAME_LISTENING) {
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flyktstatic void busname_enter_dead(BusName *n, BusNameResult f) {
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt busname_set_state(n, n->result != BUSNAME_SUCCESS ? BUSNAME_FAILED : BUSNAME_DEAD);
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flyktstatic void busname_enter_listening(BusName *n) {
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt if (r < 0) {
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt log_warning_unit(UNIT(n)->id, "%s failed to listen on bus names: %s", UNIT(n)->id, strerror(-r));
859cca44f834ab1cc3e41fa6b94744f1856ab027Patrik Flykt if (r < 0) {
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt log_warning_unit(UNIT(n)->id, "%s failed to watch names: %s", UNIT(n)->id, strerror(-r));
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt bool pending = false;
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt /* We don't take conenctions anymore if we are supposed to
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt * shut down anyway */
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt log_debug_unit(UNIT(n)->id, "Suppressing activation request on %s since unit stop is scheduled.", UNIT(n)->id);
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt /* Flush all queued activation reqeuest by closing and reopening the connection */
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt /* If there's already a start pending don't bother to do
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt * anything */
947527f8326d3591f252c48fee5426a563f03544Patrik Flykt SET_FOREACH(other, UNIT(n)->dependencies[UNIT_TRIGGERS], i)
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flykt r = manager_add_job(UNIT(n)->manager, JOB_START, UNIT_DEREF(n->service), JOB_REPLACE, true, &error, NULL);
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flykt log_warning_unit(UNIT(n)->id, "%s failed to queue service startup job: %s", UNIT(n)->id, bus_error_message(&error, r));
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flykt busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flykt if (UNIT(service)->load_state != UNIT_LOADED) {
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flykt log_error_unit(u->id, "Bus service %s not loaded, refusing.", UNIT(service)->id);
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flykt assert(IN_SET(n->state, BUSNAME_DEAD, BUSNAME_FAILED));
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flykt assert(n->state == BUSNAME_LISTENING || n->state == BUSNAME_RUNNING);
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flyktstatic int busname_serialize(Unit *u, FILE *f, FDSet *fds) {
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flykt unit_serialize_item(u, f, "state", busname_state_to_string(n->state));
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flykt unit_serialize_item(u, f, "result", busname_result_to_string(n->result));
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flykt if (n->starter_fd >= 0) {
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flykt unit_serialize_item_format(u, f, "starter-fd", "%i", copy);
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flyktstatic int busname_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flykt log_debug_unit(u->id, "Failed to parse state value %s", value);
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flykt log_debug_unit(u->id, "Failed to parse result value %s", value);
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt log_debug_unit(u->id, "Failed to parse starter fd value %s", value);
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt log_debug_unit(u->id, "Unknown serialization key '%s'", key);
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt_pure_ static UnitActiveState busname_active_state(Unit *u) {
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt return state_translation_table[BUSNAME(u)->state];
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt_pure_ static const char *busname_sub_state_to_string(Unit *u) {
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt return busname_state_to_string(BUSNAME(u)->state);
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flyktstatic int busname_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt log_debug_unit(UNIT(n)->id, "Activation request on %s", UNIT(n)->id);
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt log_error_unit(UNIT(n)->id, "%s: Got unexpected poll event (0x%x) on starter fd.",
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
5e256ea7d3d556b3a1fb5c1faa94ec6a8833e53ePatrik Flyktstatic void busname_trigger_notify(Unit *u, Unit *other) {
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt if (!IN_SET(n->state, BUSNAME_RUNNING, BUSNAME_LISTENING))
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt if (other->load_state != UNIT_LOADED || other->type != UNIT_SERVICE)
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt if (s->state == SERVICE_FAILED && s->result == SERVICE_FAILURE_START_LIMIT)
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt busname_enter_dead(n, BUSNAME_FAILURE_SERVICE_FAILED_PERMANENT);
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt SERVICE_STOP, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL,
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL,
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flyktstatic const char* const busname_state_table[_BUSNAME_STATE_MAX] = {
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik FlyktDEFINE_STRING_TABLE_LOOKUP(busname_state, BusNameState);
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flyktstatic const char* const busname_result_table[_BUSNAME_RESULT_MAX] = {
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik FlyktDEFINE_STRING_TABLE_LOOKUP(busname_result, BusNameResult);
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt "Install\0",
813e3a6ffcd094696001716480bbd68008cc54c8Patrik Flykt .sub_state_to_string = busname_sub_state_to_string,
2ea8857effb833615b16d10fc7a19a7104c19e13Patrik Flykt .bus_interface = "org.freedesktop.systemd1.BusName",
.finished_stop_job = {