summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSonny Sasaka <sonnysasaka@chromium.org>2020-08-21 11:01:06 -0700
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2020-08-21 13:15:37 -0700
commit291dbf2c94ed956c2269097d1ed859488b08c2bd (patch)
treea7cab7c0676723f38cf27b57c48668e29df92355
parent39ca6601a0f6a1e2641d3849f79bc8f91e368546 (diff)
downloadbluez-291dbf2c94ed956c2269097d1ed859488b08c2bd.tar.gz
device: Fix race condition between device connection and disconnection
When Connect() is called and waiting for return, dev_disconnected may be called due to MGMT_EV_DEVICE_DISCONNECTED event from kernel. In that case reply to client that the connection failed otherwise the dbus method will timeout because bluetoothd never replies. Tested with simulation of a lot of Connect() to bluetooth devices and check that error is returned from bluetoothd rather than dbus timeout when this race condition happens.
-rw-r--r--src/device.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/src/device.c b/src/device.c
index 7b7808405..f59b6c1d0 100644
--- a/src/device.c
+++ b/src/device.c
@@ -3006,6 +3006,7 @@ void device_add_connection(struct btd_device *dev, uint8_t bdaddr_type)
void device_remove_connection(struct btd_device *device, uint8_t bdaddr_type)
{
struct bearer_state *state = get_state(device, bdaddr_type);
+ DBusMessage *reply;
if (!state->connected)
return;
@@ -3020,6 +3021,18 @@ void device_remove_connection(struct btd_device *device, uint8_t bdaddr_type)
device->disconn_timer = 0;
}
+ /* This could be executed while the client is waiting for Connect() but
+ * att_connect_cb has not been invoked.
+ * In that case reply the client that the connection failed.
+ */
+ if (device->connect) {
+ DBG("connection removed while Connect() is waiting reply");
+ reply = btd_error_failed(device->connect, "Disconnected early");
+ g_dbus_send_message(dbus_conn, reply);
+ dbus_message_unref(device->connect);
+ device->connect = NULL;
+ }
+
while (device->disconnects) {
DBusMessage *msg = device->disconnects->data;