diff options
author | Lennart Poettering <lennart@poettering.net> | 2013-12-12 22:21:25 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2013-12-13 04:06:43 +0100 |
commit | 6203e07a83214a55bb1f88508fcda2005c601dea (patch) | |
tree | 51112fe80de37b9f7cfd59f703fafdc624ae02d7 /src/libsystemd-bus/bus-util.c | |
parent | 6e41a3e53d858f30e131c62350f51465558ca55c (diff) |
event: rework sd-event exit logic
With this change a failing event source handler will not cause the
entire event loop to fail. Instead, we just disable the specific event
source, log a message at debug level and go on.
This also introduces a new concept of "exit code" which can be stored in
the event loop and is returned by sd_event_loop(). We also rename "quit"
to "exit" everywhere else.
Altogether this should make things more robus and keep errors local
while still providing a way to return event loop errors in a clear way.
Diffstat (limited to 'src/libsystemd-bus/bus-util.c')
-rw-r--r-- | src/libsystemd-bus/bus-util.c | 23 |
1 files changed, 16 insertions, 7 deletions
diff --git a/src/libsystemd-bus/bus-util.c b/src/libsystemd-bus/bus-util.c index 3afcb82bcb..30ee67e850 100644 --- a/src/libsystemd-bus/bus-util.c +++ b/src/libsystemd-bus/bus-util.c @@ -35,18 +35,18 @@ #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; @@ -55,6 +55,11 @@ int bus_async_unregister_and_quit(sd_event *e, sd_bus *bus, const char *name) { assert(bus); assert(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; @@ -71,7 +76,7 @@ int bus_async_unregister_and_quit(sd_event *e, sd_bus *bus, const char *name) { if (r < 0) return -ENOMEM; - r = sd_bus_add_match(bus, match, quit_callback, e); + r = sd_bus_add_match(bus, match, name_owner_change_callback, e); if (r < 0) return r; @@ -84,7 +89,7 @@ int bus_async_unregister_and_quit(sd_event *e, sd_bus *bus, const char *name) { int bus_event_loop_with_idle(sd_event *e, sd_bus *bus, const char *name, usec_t timeout) { bool exiting = false; - int r; + int r, code; assert(e); assert(bus); @@ -103,7 +108,7 @@ int bus_event_loop_with_idle(sd_event *e, sd_bus *bus, const char *name, usec_t 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; @@ -111,7 +116,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) { |