1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include "bus-kernel.h"
24 #include "bus-internal.h"
27 #include "dbus-busname.h"
30 static const UnitActiveState state_translation_table[_BUSNAME_STATE_MAX] = {
31 [BUSNAME_DEAD] = UNIT_INACTIVE,
32 [BUSNAME_LISTENING] = UNIT_ACTIVE,
33 [BUSNAME_RUNNING] = UNIT_ACTIVE,
34 [BUSNAME_FAILED] = UNIT_FAILED
37 static int busname_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
39 static void busname_init(Unit *u) {
40 BusName *n = BUSNAME(u);
43 assert(u->load_state == UNIT_STUB);
48 static void busname_done(Unit *u) {
49 BusName *n = BUSNAME(u);
56 unit_ref_unset(&n->service);
58 n->event_source = sd_event_source_unref(n->event_source);
60 if (n->starter_fd >= 0) {
61 close_nointr_nofail(n->starter_fd);
66 static int busname_add_default_default_dependencies(BusName *n) {
71 r = unit_add_dependency_by_name(UNIT(n), UNIT_BEFORE, SPECIAL_BUSNAMES_TARGET, NULL, true);
75 if (UNIT(n)->manager->running_as == SYSTEMD_SYSTEM) {
76 r = unit_add_two_dependencies_by_name(UNIT(n), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true);
81 return unit_add_two_dependencies_by_name(UNIT(n), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
84 static int busname_add_extras(BusName *n) {
91 n->name = unit_name_to_prefix(u->id);
96 if (!u->description) {
97 r = unit_set_description(u, n->name);
102 if (!UNIT_DEREF(n->service)) {
105 r = unit_load_related_unit(u, ".service", &x);
109 unit_ref_set(&n->service, x);
112 r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, UNIT_DEREF(n->service), true);
116 if (u->default_dependencies) {
117 r = busname_add_default_default_dependencies(n);
127 static int busname_verify(BusName *n) {
132 if (UNIT(n)->load_state != UNIT_LOADED)
135 if (!service_name_is_valid(n->name)) {
136 log_error_unit(UNIT(n)->id, "%s's Name= setting is not a valid service name Refusing.", UNIT(n)->id);
140 e = strappenda(n->name, ".busname");
141 if (!unit_has_name(UNIT(n), e)) {
142 log_error_unit(UNIT(n)->id, "%s's Name= setting doesn't match unit name. Refusing.", UNIT(n)->id);
149 static int busname_load(Unit *u) {
150 BusName *n = BUSNAME(u);
154 assert(u->load_state == UNIT_STUB);
156 r = unit_load_fragment_and_dropin(u);
160 if (u->load_state == UNIT_LOADED) {
161 /* This is a new unit? Then let's add in some extras */
162 r = busname_add_extras(n);
167 return busname_verify(n);
170 static void busname_dump(Unit *u, FILE *f, const char *prefix) {
171 BusName *n = BUSNAME(u);
177 "%sBus Name State: %s\n"
180 prefix, busname_state_to_string(n->state),
181 prefix, busname_result_to_string(n->result),
185 static void busname_unwatch_fd(BusName *n) {
190 if (n->event_source) {
191 r = sd_event_source_set_enabled(n->event_source, SD_EVENT_OFF);
193 log_debug_unit(UNIT(n)->id, "Failed to disable event source.");
197 static void busname_close_fd(BusName *n) {
200 busname_unwatch_fd(n);
202 if (n->starter_fd <= 0)
205 close_nointr_nofail(n->starter_fd);
209 static int busname_watch_fd(BusName *n) {
214 if (n->starter_fd < 0)
218 r = sd_event_source_set_enabled(n->event_source, SD_EVENT_ON);
220 r = sd_event_add_io(UNIT(n)->manager->event, n->starter_fd, EPOLLIN, busname_dispatch_io, n, &n->event_source);
222 log_warning_unit(UNIT(n)->id, "Failed to watch starter fd: %s", strerror(-r));
223 busname_unwatch_fd(n);
230 static int busname_open_fd(BusName *n) {
233 if (n->starter_fd >= 0)
236 n->starter_fd = bus_kernel_create_starter(UNIT(n)->manager->running_as == SYSTEMD_SYSTEM ? "system" : "user", n->name);
237 if (n->starter_fd < 0) {
238 log_warning_unit(UNIT(n)->id, "Failed to create starter fd: %s", strerror(-n->starter_fd));
239 return n->starter_fd;
245 static void busname_set_state(BusName *n, BusNameState state) {
246 BusNameState old_state;
249 old_state = n->state;
252 if (state != BUSNAME_LISTENING)
253 busname_unwatch_fd(n);
255 if (!IN_SET(state, BUSNAME_LISTENING, BUSNAME_RUNNING))
258 if (state != old_state)
259 log_debug_unit(UNIT(n)->id, "%s changed %s -> %s",
260 UNIT(n)->id, busname_state_to_string(old_state), busname_state_to_string(state));
262 unit_notify(UNIT(n), state_translation_table[old_state], state_translation_table[state], true);
265 static int busname_coldplug(Unit *u) {
266 BusName *n = BUSNAME(u);
270 assert(n->state == BUSNAME_DEAD);
272 if (n->deserialized_state == n->state)
275 if (IN_SET(n->deserialized_state, BUSNAME_LISTENING, BUSNAME_RUNNING)) {
276 r = busname_open_fd(n);
281 if (n->deserialized_state == BUSNAME_LISTENING) {
282 r = busname_watch_fd(n);
287 busname_set_state(n, n->deserialized_state);
291 static void busname_enter_dead(BusName *n, BusNameResult f) {
294 if (f != BUSNAME_SUCCESS)
297 busname_set_state(n, n->result != BUSNAME_SUCCESS ? BUSNAME_FAILED : BUSNAME_DEAD);
300 static void busname_enter_listening(BusName *n) {
305 r = busname_open_fd(n);
307 log_warning_unit(UNIT(n)->id, "%s failed to listen on bus names: %s", UNIT(n)->id, strerror(-r));
311 r = busname_watch_fd(n);
313 log_warning_unit(UNIT(n)->id, "%s failed to watch names: %s", UNIT(n)->id, strerror(-r));
317 busname_set_state(n, BUSNAME_LISTENING);
321 busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
324 static void busname_enter_running(BusName *n) {
325 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
326 bool pending = false;
333 /* We don't take conenctions anymore if we are supposed to
334 * shut down anyway */
336 if (unit_stop_pending(UNIT(n))) {
337 log_debug_unit(UNIT(n)->id, "Suppressing activation request on %s since unit stop is scheduled.", UNIT(n)->id);
339 /* Flush all queued activation reqeuest by closing and reopening the connection */
340 bus_kernel_drop_one(n->starter_fd);
342 busname_enter_listening(n);
346 /* If there's already a start pending don't bother to do
348 SET_FOREACH(other, UNIT(n)->dependencies[UNIT_TRIGGERS], i)
349 if (unit_active_or_pending(other)) {
355 r = manager_add_job(UNIT(n)->manager, JOB_START, UNIT_DEREF(n->service), JOB_REPLACE, true, &error, NULL);
360 busname_set_state(n, BUSNAME_RUNNING);
364 log_warning_unit(UNIT(n)->id, "%s failed to queue service startup job: %s", UNIT(n)->id, bus_error_message(&error, r));
365 busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
368 static int busname_start(Unit *u) {
369 BusName *n = BUSNAME(u);
373 if (UNIT_ISSET(n->service)) {
376 service = SERVICE(UNIT_DEREF(n->service));
378 if (UNIT(service)->load_state != UNIT_LOADED) {
379 log_error_unit(u->id, "Bus service %s not loaded, refusing.", UNIT(service)->id);
384 assert(IN_SET(n->state, BUSNAME_DEAD, BUSNAME_FAILED));
386 n->result = BUSNAME_SUCCESS;
387 busname_enter_listening(n);
392 static int busname_stop(Unit *u) {
393 BusName *n = BUSNAME(u);
396 assert(n->state == BUSNAME_LISTENING || n->state == BUSNAME_RUNNING);
398 busname_enter_dead(n, BUSNAME_SUCCESS);
402 static int busname_serialize(Unit *u, FILE *f, FDSet *fds) {
403 BusName *n = BUSNAME(u);
409 unit_serialize_item(u, f, "state", busname_state_to_string(n->state));
410 unit_serialize_item(u, f, "result", busname_result_to_string(n->result));
412 if (n->starter_fd >= 0) {
415 copy = fdset_put_dup(fds, n->starter_fd);
419 unit_serialize_item_format(u, f, "starter-fd", "%i", copy);
425 static int busname_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
426 BusName *n = BUSNAME(u);
432 if (streq(key, "state")) {
435 state = busname_state_from_string(value);
437 log_debug_unit(u->id, "Failed to parse state value %s", value);
439 n->deserialized_state = state;
441 } else if (streq(key, "result")) {
444 f = busname_result_from_string(value);
446 log_debug_unit(u->id, "Failed to parse result value %s", value);
447 else if (f != BUSNAME_SUCCESS)
450 } else if (streq(key, "starter-fd")) {
453 if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
454 log_debug_unit(u->id, "Failed to parse starter fd value %s", value);
456 if (n->starter_fd >= 0)
457 close_nointr_nofail(n->starter_fd);
458 n->starter_fd = fdset_remove(fds, fd);
461 log_debug_unit(u->id, "Unknown serialization key '%s'", key);
466 _pure_ static UnitActiveState busname_active_state(Unit *u) {
469 return state_translation_table[BUSNAME(u)->state];
472 _pure_ static const char *busname_sub_state_to_string(Unit *u) {
475 return busname_state_to_string(BUSNAME(u)->state);
478 static int busname_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
479 BusName *n = userdata;
484 if (n->state != BUSNAME_LISTENING)
487 log_debug_unit(UNIT(n)->id, "Activation request on %s", UNIT(n)->id);
489 if (revents != EPOLLIN) {
490 log_error_unit(UNIT(n)->id, "%s: Got unexpected poll event (0x%x) on starter fd.",
491 UNIT(n)->id, revents);
495 busname_enter_running(n);
499 busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
503 static void busname_reset_failed(Unit *u) {
504 BusName *n = BUSNAME(u);
508 if (n->state == BUSNAME_FAILED)
509 busname_set_state(n, BUSNAME_DEAD);
511 n->result = BUSNAME_SUCCESS;
514 static void busname_trigger_notify(Unit *u, Unit *other) {
515 BusName *n = BUSNAME(u);
521 if (!IN_SET(n->state, BUSNAME_RUNNING, BUSNAME_LISTENING))
524 if (other->load_state != UNIT_LOADED || other->type != UNIT_SERVICE)
529 if (s->state == SERVICE_FAILED && s->result == SERVICE_FAILURE_START_LIMIT)
530 busname_enter_dead(n, BUSNAME_FAILURE_SERVICE_FAILED_PERMANENT);
531 else if (IN_SET(s->state,
532 SERVICE_DEAD, SERVICE_FAILED,
533 SERVICE_STOP, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL,
534 SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL,
535 SERVICE_AUTO_RESTART))
536 busname_enter_listening(n);
539 static const char* const busname_state_table[_BUSNAME_STATE_MAX] = {
540 [BUSNAME_DEAD] = "dead",
541 [BUSNAME_LISTENING] = "listening",
542 [BUSNAME_RUNNING] = "running",
543 [BUSNAME_FAILED] = "failed"
546 DEFINE_STRING_TABLE_LOOKUP(busname_state, BusNameState);
548 static const char* const busname_result_table[_BUSNAME_RESULT_MAX] = {
549 [BUSNAME_SUCCESS] = "success",
550 [BUSNAME_FAILURE_RESOURCES] = "resources",
553 DEFINE_STRING_TABLE_LOOKUP(busname_result, BusNameResult);
555 const UnitVTable busname_vtable = {
556 .object_size = sizeof(BusName),
562 .private_section = "BusName",
564 .init = busname_init,
565 .done = busname_done,
566 .load = busname_load,
568 .coldplug = busname_coldplug,
570 .dump = busname_dump,
572 .start = busname_start,
573 .stop = busname_stop,
575 .serialize = busname_serialize,
576 .deserialize_item = busname_deserialize_item,
578 .active_state = busname_active_state,
579 .sub_state_to_string = busname_sub_state_to_string,
581 .trigger_notify = busname_trigger_notify,
583 .reset_failed = busname_reset_failed,
585 .bus_interface = "org.freedesktop.systemd1.BusName",
586 .bus_vtable = bus_busname_vtable,
588 .status_message_formats = {
589 .finished_start_job = {
590 [JOB_DONE] = "Listening on %s.",
591 [JOB_FAILED] = "Failed to listen on %s.",
592 [JOB_DEPENDENCY] = "Dependency failed for %s.",
593 [JOB_TIMEOUT] = "Timed out starting %s.",
595 .finished_stop_job = {
596 [JOB_DONE] = "Closed %s.",
597 [JOB_FAILED] = "Failed stopping %s.",
598 [JOB_TIMEOUT] = "Timed out stopping %s.",