From 19dc2963057bda67f30adcfe1bf70b533f7310ca Mon Sep 17 00:00:00 2001 From: Josh Gao Date: Tue, 26 Mar 2019 18:47:45 -0700 Subject: adbd: wait for FUNCTIONFS_BIND for up to a second, then retry. Occasionally, after we open the functionfs endpoint and write our descriptors to it, we end up in a state where we never receive any events from ep0, presumably due to a race against some other part of the system, since adding sleeps reduces the likelihood. Add an (arbitrarily chosen) timeout for the initial FUNCTIONFS_BIND we read, and retry on failure. Bug: http://b/128679787 Test: unplug and replug a blueline 14,000 times with a usb switch board Change-Id: I4b3d5d552179ee7f3fefcc15f9575f793926f784 --- adb/daemon/usb.cpp | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'adb') diff --git a/adb/daemon/usb.cpp b/adb/daemon/usb.cpp index 8a5000336..14cdb6961 100644 --- a/adb/daemon/usb.cpp +++ b/adb/daemon/usb.cpp @@ -168,7 +168,8 @@ struct ScopedAioContext { struct UsbFfsConnection : public Connection { UsbFfsConnection(unique_fd control, unique_fd read, unique_fd write, std::promise destruction_notifier) - : stopped_(false), + : worker_started_(false), + stopped_(false), destruction_notifier_(std::move(destruction_notifier)), control_fd_(std::move(control)), read_fd_(std::move(read)), @@ -194,6 +195,7 @@ struct UsbFfsConnection : public Connection { // We need to explicitly close our file descriptors before we notify our destruction, // because the thread listening on the future will immediately try to reopen the endpoint. + aio_context_.reset(); control_fd_.reset(); read_fd_.reset(); write_fd_.reset(); @@ -274,11 +276,16 @@ struct UsbFfsConnection : public Connection { { .fd = control_fd_.get(), .events = POLLIN, .revents = 0 }, { .fd = monitor_event_fd_.get(), .events = POLLIN, .revents = 0 }, }; - int rc = TEMP_FAILURE_RETRY(adb_poll(pfd, 2, -1)); + + // If we don't see our first bind within a second, try again. + int timeout_ms = bound ? -1 : 1000; + + int rc = TEMP_FAILURE_RETRY(adb_poll(pfd, 2, timeout_ms)); if (rc == -1) { PLOG(FATAL) << "poll on USB control fd failed"; } else if (rc == 0) { - LOG(FATAL) << "poll on USB control fd returned 0"; + LOG(WARNING) << "timed out while waiting for FUNCTIONFS_BIND, trying again"; + break; } if (pfd[1].revents) { @@ -330,13 +337,13 @@ struct UsbFfsConnection : public Connection { } StopWorker(); - aio_context_.reset(); - read_fd_.reset(); - write_fd_.reset(); + HandleError("monitor thread finished"); }); } void StartWorker() { + CHECK(!worker_started_); + worker_started_ = true; worker_thread_ = std::thread([this]() { adb_thread_setname("UsbFfs-worker"); for (size_t i = 0; i < kUsbReadQueueDepth; ++i) { @@ -361,6 +368,10 @@ struct UsbFfsConnection : public Connection { } void StopWorker() { + if (!worker_started_) { + return; + } + pthread_t worker_thread_handle = worker_thread_.native_handle(); while (true) { int rc = pthread_kill(worker_thread_handle, kInterruptionSignal); @@ -590,6 +601,8 @@ struct UsbFfsConnection : public Connection { } std::thread monitor_thread_; + + bool worker_started_; std::thread worker_thread_; std::atomic stopped_; -- cgit v1.2.3