busname.c revision 16ac401407959cbc62312e61c2dd76dbc3a0793b
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering This file is part of systemd.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Copyright 2013 Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is free software; you can redistribute it and/or modify it
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering under the terms of the GNU Lesser General Public License as published by
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (at your option) any later version.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is distributed in the hope that it will be useful, but
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Lesser General Public License for more details.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering You should have received a copy of the GNU Lesser General Public License
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poetteringstatic const UnitActiveState state_translation_table[_BUSNAME_STATE_MAX] = {
3f6fd1ba65f962702753c4ad284b588e59689a23Lennart Poetteringstatic int busname_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
3f6fd1ba65f962702753c4ad284b588e59689a23Lennart Poettering n->event_source = sd_event_source_unref(n->event_source);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int busname_add_default_default_dependencies(BusName *n) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = unit_add_dependency_by_name(UNIT(n), UNIT_BEFORE, SPECIAL_BUSNAMES_TARGET, NULL, true);
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering if (UNIT(n)->manager->running_as == SYSTEMD_SYSTEM) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering r = unit_add_two_dependencies_by_name(UNIT(n), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true);
c454426c54c9beb274f415a80c64a4f1580700e7Lennart Poettering return unit_add_two_dependencies_by_name(UNIT(n), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int busname_add_extras(BusName *n) {
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering r = unit_load_related_unit(u, ".service", &x);
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, UNIT_DEREF(n->service), true);
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering r = busname_add_default_default_dependencies(n);
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering log_error_unit(UNIT(n)->id, "%s's Name= setting is not a valid service name Refusing.", UNIT(n)->id);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen log_error_unit(UNIT(n)->id, "%s's Name= setting doesn't match unit name. Refusing.", UNIT(n)->id);
fee6d013d859bc66f5c993530898fece53fab06dLennart Poettering /* This is a new unit? Then let's add in some extras */
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poetteringstatic void busname_dump(Unit *u, FILE *f, const char *prefix) {
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering "%sBus Name State: %s\n"
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering "%sResult: %s\n"
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering "%sName: %s\n",
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering prefix, busname_state_to_string(n->state),
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering prefix, busname_result_to_string(n->result),
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_event_source_set_enabled(n->event_source, SD_EVENT_OFF);
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering log_debug_unit(UNIT(n)->id, "Failed to disable event source.");
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poetteringstatic void busname_close_fd(BusName *n) {
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering r = sd_event_source_set_enabled(n->event_source, SD_EVENT_ON);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering r = sd_event_add_io(UNIT(n)->manager->event, n->starter_fd, EPOLLIN, busname_dispatch_io, n, &n->event_source);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering log_warning_unit(UNIT(n)->id, "Failed to watch starter fd: %s", strerror(-r));
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering n->starter_fd = bus_kernel_create_starter(UNIT(n)->manager->running_as == SYSTEMD_SYSTEM ? "system" : "user", n->name);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering log_warning_unit(UNIT(n)->id, "Failed to create starter fd: %s", strerror(-n->starter_fd));
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poetteringstatic void busname_set_state(BusName *n, BusNameState state) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (!IN_SET(state, BUSNAME_LISTENING, BUSNAME_RUNNING))
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering log_debug_unit(UNIT(n)->id, "%s changed %s -> %s",
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering UNIT(n)->id, busname_state_to_string(old_state), busname_state_to_string(state));
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering unit_notify(UNIT(n), state_translation_table[old_state], state_translation_table[state], true);
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering if (IN_SET(n->deserialized_state, BUSNAME_LISTENING, BUSNAME_RUNNING)) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (n->deserialized_state == BUSNAME_LISTENING) {
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering busname_set_state(n, n->deserialized_state);
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poetteringstatic void busname_enter_dead(BusName *n, BusNameResult f) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering busname_set_state(n, n->result != BUSNAME_SUCCESS ? BUSNAME_FAILED : BUSNAME_DEAD);
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poetteringstatic void busname_enter_listening(BusName *n) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering log_warning_unit(UNIT(n)->id, "%s failed to listen on bus names: %s", UNIT(n)->id, strerror(-r));
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering log_warning_unit(UNIT(n)->id, "%s failed to watch names: %s", UNIT(n)->id, strerror(-r));
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poetteringstatic void busname_enter_running(BusName *n) {
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering /* We don't take conenctions anymore if we are supposed to
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering * shut down anyway */
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering log_debug_unit(UNIT(n)->id, "Suppressing activation request on %s since unit stop is scheduled.", UNIT(n)->id);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering /* Flush all queued activation reqeuest by closing and reopening the connection */
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering /* If there's already a start pending don't bother to do
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering SET_FOREACH(other, UNIT(n)->dependencies[UNIT_TRIGGERS], i)
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering r = manager_add_job(UNIT(n)->manager, JOB_START, UNIT_DEREF(n->service), JOB_REPLACE, true, &error, NULL);
21b735e798c580e7af8c33ace9f8565860b7f8dfLennart Poettering log_warning_unit(UNIT(n)->id, "%s failed to queue service startup job: %s", UNIT(n)->id, bus_error_message(&error, r));
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering service = SERVICE(UNIT_DEREF(n->service));
6f883237f1b8a96ec0ea354866e033b6fcea9506Lennart Poettering if (UNIT(service)->load_state != UNIT_LOADED) {
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering log_error_unit(u->id, "Bus service %s not loaded, refusing.", UNIT(service)->id);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert(IN_SET(n->state, BUSNAME_DEAD, BUSNAME_FAILED));
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering assert(n->state == BUSNAME_LISTENING || n->state == BUSNAME_RUNNING);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poetteringstatic int busname_serialize(Unit *u, FILE *f, FDSet *fds) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering unit_serialize_item(u, f, "state", busname_state_to_string(n->state));
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering unit_serialize_item(u, f, "result", busname_result_to_string(n->result));
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering copy = fdset_put_dup(fds, n->starter_fd);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering unit_serialize_item_format(u, f, "starter-fd", "%i", copy);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poetteringstatic int busname_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering state = busname_state_from_string(value);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering log_debug_unit(u->id, "Failed to parse state value %s", value);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering log_debug_unit(u->id, "Failed to parse result value %s", value);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering log_debug_unit(u->id, "Failed to parse starter fd value %s", value);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering log_debug_unit(u->id, "Unknown serialization key '%s'", key);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering_pure_ static UnitActiveState busname_active_state(Unit *u) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering return state_translation_table[BUSNAME(u)->state];
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering_pure_ static const char *busname_sub_state_to_string(Unit *u) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering return busname_state_to_string(BUSNAME(u)->state);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poetteringstatic int busname_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering log_debug_unit(UNIT(n)->id, "Activation request on %s", UNIT(n)->id);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering log_error_unit(UNIT(n)->id, "%s: Got unexpected poll event (0x%x) on starter fd.",
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poetteringstatic void busname_reset_failed(Unit *u) {
e7e55dbdc38f929805ab2407fbd50886043a9e7cDavid Herrmannstatic void busname_trigger_notify(Unit *u, Unit *other) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!IN_SET(n->state, BUSNAME_RUNNING, BUSNAME_LISTENING))
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering if (other->load_state != UNIT_LOADED || other->type != UNIT_SERVICE)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (s->state == SERVICE_FAILED && s->result == SERVICE_FAILURE_START_LIMIT)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering busname_enter_dead(n, BUSNAME_FAILURE_SERVICE_FAILED_PERMANENT);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering SERVICE_STOP, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL,
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic const char* const busname_state_table[_BUSNAME_STATE_MAX] = {
1ee306e1248866617c96ed9f4263f375588ad838Lennart PoetteringDEFINE_STRING_TABLE_LOOKUP(busname_state, BusNameState);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic const char* const busname_result_table[_BUSNAME_RESULT_MAX] = {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering [BUSNAME_FAILURE_RESOURCES] = "resources",
1ee306e1248866617c96ed9f4263f375588ad838Lennart PoetteringDEFINE_STRING_TABLE_LOOKUP(busname_result, BusNameResult);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering .deserialize_item = busname_deserialize_item,
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering .sub_state_to_string = busname_sub_state_to_string,
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering .trigger_notify = busname_trigger_notify,
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering .bus_interface = "org.freedesktop.systemd1.BusName",
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering .bus_changing_properties = bus_busname_changing_properties,
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering [JOB_FAILED] = "Failed to listen on %s.",
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering [JOB_DEPENDENCY] = "Dependency failed for %s.",
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering [JOB_TIMEOUT] = "Timed out starting %s.",
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering [JOB_TIMEOUT] = "Timed out stopping %s.",