diff options
author | Sonny Sasaka <sonnysasaka@chromium.org> | 2020-08-21 11:01:06 -0700 |
---|---|---|
committer | Luiz Augusto von Dentz <luiz.von.dentz@intel.com> | 2020-08-21 13:15:37 -0700 |
commit | 291dbf2c94ed956c2269097d1ed859488b08c2bd (patch) | |
tree | a7cab7c0676723f38cf27b57c48668e29df92355 | |
parent | 39ca6601a0f6a1e2641d3849f79bc8f91e368546 (diff) | |
download | bluez-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.c | 13 |
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; |