summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2014-04-13 18:25:10 -0700
committerLennart Poettering <lennart@poettering.net>2014-04-13 18:34:55 -0700
commit2a0abe5b6d4997baaeb3353eee8685d92b2060e9 (patch)
treed2950f822a12c3c82f8ff6a281ce5f16cdcd5e38
parent6e0369b0ff3909baec25c6ab31b5ddf5c4ae0f3f (diff)
bus: process AddMatch/RemoveMatch driver call in proxy
Previously, AddMatch/RemoveMatch calls where processed exclusively in the proxy. That's racy however, since subscribing to a signal might not complete before the signal is sent due to some subsequent method call. Hence, in order to expose the same ordering guarantees as dbus1 process the AddMatch/RemoveMatch calls from the proxy, so that they are dispatched synchronously to all following messages, thus fixing the race. Ultimately, we should probabably dissolve the driver entirely into the proxy, as it is purely a compatibility feature anyway...
-rw-r--r--src/bus-driverd/bus-driverd.c2
-rw-r--r--src/bus-proxyd/bus-proxyd.c68
2 files changed, 61 insertions, 9 deletions
diff --git a/src/bus-driverd/bus-driverd.c b/src/bus-driverd/bus-driverd.c
index 4756c481bd..0b5c9b51f3 100644
--- a/src/bus-driverd/bus-driverd.c
+++ b/src/bus-driverd/bus-driverd.c
@@ -800,6 +800,7 @@ static int driver_unsupported(sd_bus *bus, sd_bus_message *m, void *userdata, sd
static const sd_bus_vtable driver_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_METHOD("AddMatch", "s", NULL, driver_add_match, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("RemoveMatch", "s", NULL, driver_remove_match, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("GetConnectionSELinuxSecurityContext", "s", "ay", driver_get_security_context, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("GetConnectionUnixProcessID", "s", "u", driver_get_pid, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("GetConnectionUnixUser", "s", "u", driver_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
@@ -812,7 +813,6 @@ static const sd_bus_vtable driver_vtable[] = {
SD_BUS_METHOD("NameHasOwner", "s", "b", driver_name_has_owner, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("ReleaseName", "s", "u", driver_release_name, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("ReloadConfig", NULL, NULL, driver_unsupported, SD_BUS_VTABLE_DEPRECATED),
- SD_BUS_METHOD("RemoveMatch", "s", NULL, driver_remove_match, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("RequestName", "su", "u", driver_request_name, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("StartServiceByName", "su", "u", driver_start_service_by_name, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("UpdateActivationEnvironment", "a{ss}", NULL, driver_update_environment, 0),
diff --git a/src/bus-proxyd/bus-proxyd.c b/src/bus-proxyd/bus-proxyd.c
index 80f83e777f..5511ee49de 100644
--- a/src/bus-proxyd/bus-proxyd.c
+++ b/src/bus-proxyd/bus-proxyd.c
@@ -289,6 +289,47 @@ static int process_policy(sd_bus *a, sd_bus *b, sd_bus_message *m) {
return 1;
}
+static int process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m) {
+ int r;
+
+ assert(a);
+ assert(b);
+ assert(m);
+
+ if (!streq_ptr(sd_bus_message_get_destination(m), "org.freedesktop.DBus"))
+ return 0;
+
+ if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "AddMatch")) {
+ const char *match;
+
+ r = sd_bus_message_read(m, "s", &match);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_add_match(a, match, NULL, NULL);
+ if (r < 0)
+ return r;
+
+ return sd_bus_reply_method_return(m, NULL);
+
+ } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RemoveMatch")) {
+ const char *match;
+
+ r = sd_bus_message_read(m, "s", &match);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_remove_match(a, match, NULL, NULL);
+ if (r < 0)
+ return r;
+
+ return sd_bus_reply_method_return(m, NULL);
+ } else
+ return 0;
+
+ return r;
+}
+
static int process_hello(sd_bus *a, sd_bus *b, sd_bus_message *m, bool *got_hello) {
_cleanup_bus_message_unref_ sd_bus_message *n = NULL;
bool is_hello;
@@ -696,17 +737,28 @@ int main(int argc, char *argv[]) {
goto finish;
}
- k = sd_bus_send(a, m, NULL);
+ k = process_driver(a, b, m);
if (k < 0) {
- if (r == -ECONNRESET)
- r = 0;
- else {
- r = k;
- log_error("Failed to send message: %s", strerror(-r));
- }
-
+ r = k;
+ log_error("Failed to process driver calls: %s", strerror(-r));
goto finish;
}
+
+ if (k > 0)
+ r = k;
+ else {
+ k = sd_bus_send(a, m, NULL);
+ if (k < 0) {
+ if (r == -ECONNRESET)
+ r = 0;
+ else {
+ r = k;
+ log_error("Failed to send message: %s", strerror(-r));
+ }
+
+ goto finish;
+ }
+ }
}
}