From d1a3e8f1ab653831a3cc4c2a90fb0f8b7a2a95ac Mon Sep 17 00:00:00 2001 From: Josh Gao Date: Tue, 30 May 2017 17:03:41 -0700 Subject: [PATCH] adb: fix deadlock. libusb hotplug callbacks are called with the libusb lock taken, and we call into libusb with our local mutex, so we need to enforce an ordering between the two. Instead of calling device_connected or device_disconnected directly, enqueue them onto the main thread. Bug: http://b/62200735 Test: manually hotplugged a device Change-Id: Ic5d55db83b47f4bb60f124ce94ddfe06f5f1a0c6 --- adb/client/usb_libusb.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/adb/client/usb_libusb.cpp b/adb/client/usb_libusb.cpp index fc32469fa..9477c5620 100644 --- a/adb/client/usb_libusb.cpp +++ b/adb/client/usb_libusb.cpp @@ -427,11 +427,15 @@ static void device_disconnected(libusb_device* device) { static int hotplug_callback(libusb_context*, libusb_device* device, libusb_hotplug_event event, void*) { - if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED) { - device_connected(device); - } else if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT) { - device_disconnected(device); - } + // We're called with the libusb lock taken. Call these on the main thread outside of this + // function so that the usb_handle mutex is always taken before the libusb mutex. + fdevent_run_on_main_thread([device, event]() { + if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED) { + device_connected(device); + } else if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT) { + device_disconnected(device); + } + }); return 0; }