device: Fix race condition between device connection and disconnection
authorSonny Sasaka <sonnysasaka@chromium.org>
Fri, 21 Aug 2020 18:01:06 +0000 (11:01 -0700)
committerAyush Garg <ayush.garg@samsung.com>
Mon, 12 Apr 2021 09:00:50 +0000 (14:30 +0530)
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.

Signed-off-by: Anuj Jain <anuj01.jain@samsung.com>
Signed-off-by: Ayush Garg <ayush.garg@samsung.com>
src/device.c

index 776cacd..2e3a80b 100644 (file)
@@ -4753,6 +4753,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;
 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
        char *dev_name = device->name;
 #endif
@@ -4782,6 +4783,18 @@ void device_remove_connection(struct btd_device *device, uint8_t bdaddr_type)
        }
 #endif
 
+       /* 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;