summaryrefslogtreecommitdiffstats
path: root/src/libsystemd/sd-bus
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/libsystemd/sd-bus/bus-socket.c22
-rw-r--r--src/libsystemd/sd-bus/sd-bus.c18
-rw-r--r--src/libsystemd/sd-bus/test-bus-watch-bind.c9
3 files changed, 31 insertions, 18 deletions
diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c
index c94befe..e193e71 100644
--- a/src/libsystemd/sd-bus/bus-socket.c
+++ b/src/libsystemd/sd-bus/bus-socket.c
@@ -725,12 +725,12 @@ static int bus_socket_inotify_setup(sd_bus *b) {
assert(b->sockaddr.sa.sa_family == AF_UNIX);
assert(b->sockaddr.un.sun_path[0] != 0);
- /* Sets up an inotify fd in case watch_bind is enabled: wait until the configured AF_UNIX file system socket
- * appears before connecting to it. The implemented is pretty simplistic: we just subscribe to relevant changes
- * to all prefix components of the path, and every time we get an event for that we try to reconnect again,
- * without actually caring what precisely the event we got told us. If we still can't connect we re-subscribe
- * to all relevant changes of anything in the path, so that our watches include any possibly newly created path
- * components. */
+ /* Sets up an inotify fd in case watch_bind is enabled: wait until the configured AF_UNIX file system
+ * socket appears before connecting to it. The implemented is pretty simplistic: we just subscribe to
+ * relevant changes to all components of the path, and every time we get an event for that we try to
+ * reconnect again, without actually caring what precisely the event we got told us. If we still
+ * can't connect we re-subscribe to all relevant changes of anything in the path, so that our watches
+ * include any possibly newly created path components. */
if (b->inotify_fd < 0) {
b->inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
@@ -749,17 +749,17 @@ static int bus_socket_inotify_setup(sd_bus *b) {
if (r < 0)
goto fail;
- /* Watch all parent directories, and don't mind any prefix that doesn't exist yet. For the innermost directory
- * that exists we want to know when files are created or moved into it. For all parents of it we just care if
- * they are removed or renamed. */
+ /* Watch all components of the path, and don't mind any prefix that doesn't exist yet. For the
+ * innermost directory that exists we want to know when files are created or moved into it. For all
+ * parents of it we just care if they are removed or renamed. */
if (!GREEDY_REALLOC(new_watches, n + 1)) {
r = -ENOMEM;
goto fail;
}
- /* Start with the top-level directory, which is a bit simpler than the rest, since it can't be a symlink, and
- * always exists */
+ /* Start with the top-level directory, which is a bit simpler than the rest, since it can't be a
+ * symlink, and always exists */
wd = inotify_add_watch(b->inotify_fd, "/", IN_CREATE|IN_MOVED_TO);
if (wd < 0) {
r = log_debug_errno(errno, "Failed to add inotify watch on /: %m");
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
index 3c91dd3..37fb888 100644
--- a/src/libsystemd/sd-bus/sd-bus.c
+++ b/src/libsystemd/sd-bus/sd-bus.c
@@ -3040,7 +3040,7 @@ null_message:
return r;
}
-static int bus_exit_now(sd_bus *bus) {
+static int bus_exit_now(sd_bus *bus, sd_event *event) {
assert(bus);
/* Exit due to close, if this is requested. If this is bus object is attached to an event source, invokes
@@ -3057,8 +3057,11 @@ static int bus_exit_now(sd_bus *bus) {
log_debug("Bus connection disconnected, exiting.");
- if (bus->event)
- return sd_event_exit(bus->event, EXIT_FAILURE);
+ if (!event)
+ event = bus->event;
+
+ if (event)
+ return sd_event_exit(event, EXIT_FAILURE);
else
exit(EXIT_FAILURE);
@@ -3120,6 +3123,7 @@ static int process_closing_reply_callback(sd_bus *bus, struct reply_callback *c)
static int process_closing(sd_bus *bus, sd_bus_message **ret) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ _cleanup_(sd_event_unrefp) sd_event *event = NULL;
struct reply_callback *c;
int r;
@@ -3154,6 +3158,10 @@ static int process_closing(sd_bus *bus, sd_bus_message **ret) {
if (r < 0)
return r;
+ /* sd_bus_close() will deref the event and set bus->event to NULL. But in bus_exit_now() we use
+ * bus->event to decide whether to return from the event loop or exit(), but given it's always NULL
+ * at that point, it always exit(). Ref it here and pass it through further down to avoid that. */
+ event = sd_event_ref(bus->event);
sd_bus_close(bus);
bus->current_message = m;
@@ -3169,7 +3177,7 @@ static int process_closing(sd_bus *bus, sd_bus_message **ret) {
/* Nothing else to do, exit now, if the condition holds */
bus->exit_triggered = true;
- (void) bus_exit_now(bus);
+ (void) bus_exit_now(bus, event);
if (ret)
*ret = TAKE_PTR(m);
@@ -4281,7 +4289,7 @@ _public_ int sd_bus_set_exit_on_disconnect(sd_bus *bus, int b) {
bus->exit_on_disconnect = b;
/* If the exit condition was triggered already, exit immediately. */
- return bus_exit_now(bus);
+ return bus_exit_now(bus, /* event= */ NULL);
}
_public_ int sd_bus_get_exit_on_disconnect(sd_bus *bus) {
diff --git a/src/libsystemd/sd-bus/test-bus-watch-bind.c b/src/libsystemd/sd-bus/test-bus-watch-bind.c
index c577330..fae2a45 100644
--- a/src/libsystemd/sd-bus/test-bus-watch-bind.c
+++ b/src/libsystemd/sd-bus/test-bus-watch-bind.c
@@ -7,6 +7,7 @@
#include "sd-id128.h"
#include "alloc-util.h"
+#include "bus-internal.h"
#include "fd-util.h"
#include "fs-util.h"
#include "mkdir.h"
@@ -27,8 +28,11 @@ static int method_foobar(sd_bus_message *m, void *userdata, sd_bus_error *ret_er
static int method_exit(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
log_info("Got Exit() call");
- assert_se(sd_event_exit(sd_bus_get_event(sd_bus_message_get_bus(m)), 1) >= 0);
- return sd_bus_reply_method_return(m, NULL);
+
+ assert_se(sd_bus_reply_method_return(m, NULL) >= 0);
+ /* Simulate D-Bus going away to test the bus_exit_now() path with exit_on_disconnect set */
+ bus_enter_closing(sd_bus_message_get_bus(m));
+ return 0;
}
static const sd_bus_vtable vtable[] = {
@@ -100,6 +104,7 @@ static void* thread_server(void *p) {
log_debug("Accepted server connection");
assert_se(sd_bus_new(&bus) >= 0);
+ assert_se(sd_bus_set_exit_on_disconnect(bus, true) >= 0);
assert_se(sd_bus_set_description(bus, "server") >= 0);
assert_se(sd_bus_set_fd(bus, bus_fd, bus_fd) >= 0);
assert_se(sd_bus_set_server(bus, true, id) >= 0);