summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikel Astiz <mikel.astiz@bmw-carit.de>2013-01-30 09:30:31 +0100
committerTanu Kaskinen <tanuk@iki.fi>2013-02-18 19:35:28 +0200
commit1db09d30138c54de64f8e197eb6d60b8a04d31c8 (patch)
treed69a6af8c6f755832cc3309d7bba5d4aecfadadd
parent88a7b31ca7d1ec38b68e7bfd99e2e53afe96cfcf (diff)
reserve: Fix leaking NameLost signals after release+acquirestable-3.x
The use of the pseudo-blocking D-Bus calls leads to the problem that NameLost signals are received after the reply to ReleaseName(). The problem with this is that a later acquisition of the same audio device can potentially receive the NameLost signal corresponding to the previous instance, due to the fact that the signal hasn't been popped from the D-Bus message queue. The simplest approach to solve this problem is to poll the actual name owner from the D-Bus daemon, in order to make sure that we did really lose the name. The proposal uses a blocking call to GetNameOwner to avoid incosistent states in the internal APIs: it would otherwise be possible to have a "busy" device before the reservation has been lost, in the unlikely case if some other process acquires the name before we got the confirmation that the NameLost was actually true.
-rw-r--r--src/modules/reserve.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/src/modules/reserve.c b/src/modules/reserve.c
index bbb67731..f78805ed 100644
--- a/src/modules/reserve.c
+++ b/src/modules/reserve.c
@@ -293,6 +293,7 @@ static DBusHandlerResult filter_handler(
rd_device *d;
DBusError error;
+ char *name_owner = NULL;
dbus_error_init(&error);
@@ -310,6 +311,21 @@ static DBusHandlerResult filter_handler(
goto invalid;
if (strcmp(name, d->service_name) == 0 && d->owning) {
+ /* Verify the actual owner of the name to avoid leaked NameLost
+ * signals from previous reservations. The D-Bus daemon will send
+ * all messages asynchronously in the correct order, but we could
+ * potentially process them too late due to the pseudo-blocking
+ * call mechanism used during both acquisition and release. This
+ * can happen if we release the device and immediately after
+ * reacquire it before NameLost is processed. */
+ if (!d->gave_up) {
+ const char *un;
+
+ if ((un = dbus_bus_get_unique_name(c)) && rd_dbus_get_name_owner(c, d->service_name, &name_owner, &error) == 0)
+ if (strcmp(name_owner, un) == 0)
+ goto invalid; /* Name still owned by us */
+ }
+
d->owning = 0;
if (!d->gave_up) {
@@ -326,6 +342,7 @@ static DBusHandlerResult filter_handler(
}
invalid:
+ free(name_owner);
dbus_error_free(&error);
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;