X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flibsystemd-bus%2Fbus-util.c;h=425f63a0fcd073e5e34a5defe7729890a9aa5f6c;hb=ab9001a1e3dc6e60d0cdf53363dc5d18dcc382fd;hp=9a42b051aaf4774406b1e9e9ee97b55a52ef8691;hpb=fe2b58a4ff8dc1cdf7081bd071bad8450db51423;p=elogind.git diff --git a/src/libsystemd-bus/bus-util.c b/src/libsystemd-bus/bus-util.c index 9a42b051a..425f63a0f 100644 --- a/src/libsystemd-bus/bus-util.c +++ b/src/libsystemd-bus/bus-util.c @@ -35,30 +35,48 @@ #include "bus-util.h" #include "bus-internal.h" -static int quit_callback(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { +static int name_owner_change_callback(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { sd_event *e = userdata; assert(bus); assert(m); assert(e); - sd_event_request_quit(e); + sd_event_exit(e, 0); return 1; } -int bus_async_unregister_and_quit(sd_event *e, sd_bus *bus, const char *name) { +int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name) { _cleanup_free_ char *match = NULL; + const char *unique; int r; assert(e); assert(bus); assert(name); - r = asprintf(&match, "type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameLost',arg0='%s'", name); + /* We unregister the name here and then wait for the + * NameOwnerChanged signal for this event to arrive before we + * quit. We do this in order to make sure that any queued + * requests are still processed before we really exit. */ + + r = sd_bus_get_unique_name(bus, &unique); if (r < 0) return r; - r = sd_bus_add_match(bus, match, quit_callback, e); + r = asprintf(&match, + "sender='org.freedesktop.DBus'," + "type='signal'," + "interface='org.freedesktop.DBus'," + "member='NameOwnerChanged'," + "path='/org/freedesktop/DBus'," + "arg0='%s'," + "arg1='%s'," + "arg2=''", name, unique); + if (r < 0) + return -ENOMEM; + + r = sd_bus_add_match(bus, match, name_owner_change_callback, e); if (r < 0) return r; @@ -66,34 +84,43 @@ int bus_async_unregister_and_quit(sd_event *e, sd_bus *bus, const char *name) { if (r < 0) return r; - if (r != BUS_NAME_RELEASED) - return -EIO; - return 0; } -int bus_event_loop_with_idle(sd_event *e, sd_bus *bus, const char *name, usec_t timeout) { +int bus_event_loop_with_idle( + sd_event *e, + sd_bus *bus, + const char *name, + usec_t timeout, + check_idle_t check_idle, + void *userdata) { bool exiting = false; - int r; + int r, code; assert(e); assert(bus); assert(name); for (;;) { + bool idle; + r = sd_event_get_state(e); if (r < 0) return r; - if (r == SD_EVENT_FINISHED) break; - r = sd_event_run(e, exiting ? (uint64_t) -1 : timeout); + if (check_idle) + idle = check_idle(userdata); + else + idle = true; + + r = sd_event_run(e, exiting || !idle ? (uint64_t) -1 : timeout); if (r < 0) return r; if (r == 0 && !exiting) { - r = bus_async_unregister_and_quit(e, bus, name); + r = bus_async_unregister_and_exit(e, bus, name); if (r < 0) return r; @@ -101,7 +128,11 @@ int bus_event_loop_with_idle(sd_event *e, sd_bus *bus, const char *name, usec_t } } - return 0; + r = sd_event_get_exit_code(e, &code); + if (r < 0) + return r; + + return code; } int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) { @@ -193,8 +224,12 @@ int bus_verify_polkit( } r = sd_bus_message_enter_container(reply, 'r', "bba{ss}"); - if (r >= 0) - r = sd_bus_message_read(reply, "bb", &authorized, &challenge); + if (r < 0) + return r; + + r = sd_bus_message_read(reply, "bb", &authorized, &challenge); + if (r < 0) + return r; if (authorized) return 1; @@ -309,7 +344,7 @@ int bus_verify_polkit_async( if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) return -EACCES; - return sd_bus_error_get_errno(e); + return -sd_bus_error_get_errno(e); } r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}"); @@ -448,7 +483,7 @@ int bus_open_system_systemd(sd_bus **_bus) { if (r < 0) return r; - r = sd_bus_set_address(bus, "kernel:path=/dev/kdbus/0-system/bus"); + r = sd_bus_set_address(bus, KERNEL_SYSTEM_BUS_PATH); if (r < 0) return r; @@ -501,7 +536,7 @@ int bus_open_user_systemd(sd_bus **_bus) { if (r < 0) return r; - if (asprintf(&bus->address, "kernel:path=/dev/kdbus/%lu-user/bus", (unsigned long) getuid()) < 0) + if (asprintf(&bus->address, KERNEL_USER_BUS_FMT, (unsigned long) getuid()) < 0) return -ENOMEM; bus->bus_client = true; @@ -978,6 +1013,8 @@ int bus_map_all_properties(sd_bus *bus, r = prop->set(bus, member, m, &error, v); else r = map_basic(bus, member, m, &error, v); + if (r < 0) + return r; r = sd_bus_message_exit_container(m); if (r < 0)