diff --git a/adb/client/usb_libusb.cpp b/adb/client/usb_libusb.cpp index e7f44c685..7025f283c 100644 --- a/adb/client/usb_libusb.cpp +++ b/adb/client/usb_libusb.cpp @@ -412,8 +412,13 @@ static void device_disconnected(libusb_device* device) { if (it != usb_handles.end()) { if (!it->second->device_handle) { // If the handle is null, we were never able to open the device. - unregister_usb_transport(it->second.get()); + + // Temporarily release the usb handles mutex to avoid deadlock. + std::unique_ptr handle = std::move(it->second); usb_handles.erase(it); + lock.unlock(); + unregister_usb_transport(handle.get()); + lock.lock(); } else { // Closure of the transport will erase the usb_handle. } diff --git a/adb/transport.cpp b/adb/transport.cpp index b2e03a057..1b597fdd8 100644 --- a/adb/transport.cpp +++ b/adb/transport.cpp @@ -615,15 +615,15 @@ static void remove_transport(atransport* transport) { static void transport_unref(atransport* t) { CHECK(t != nullptr); - size_t old_refcount = t->ref_count--; - CHECK_GT(old_refcount, 0u); - - if (old_refcount == 1u) { + std::lock_guard lock(transport_lock); + CHECK_GT(t->ref_count, 0u); + t->ref_count--; + if (t->ref_count == 0) { D("transport: %s unref (kicking and closing)", t->serial); t->close(t); remove_transport(t); } else { - D("transport: %s unref (count=%zu)", t->serial, old_refcount - 1); + D("transport: %s unref (count=%zu)", t->serial, t->ref_count); } } diff --git a/adb/transport.h b/adb/transport.h index 00fad5646..374bfc30d 100644 --- a/adb/transport.h +++ b/adb/transport.h @@ -64,7 +64,7 @@ class atransport { // it's better to do this piece by piece. atransport(ConnectionState state = kCsOffline) - : id(NextTransportId()), ref_count(0), connection_state_(state) { + : id(NextTransportId()), connection_state_(state) { transport_fde = {}; protocol_version = A_VERSION; max_payload = MAX_PAYLOAD; @@ -88,7 +88,7 @@ class atransport { int fd = -1; int transport_socket = -1; fdevent transport_fde; - std::atomic ref_count; + size_t ref_count = 0; uint32_t sync_token = 0; bool online = false; TransportType type = kTransportAny;