diff options
author | Josh Gao <jmgao@google.com> | 2019-03-26 18:47:45 -0700 |
---|---|---|
committer | Josh Gao <jmgao@google.com> | 2019-03-27 18:04:45 +0000 |
commit | 19dc2963057bda67f30adcfe1bf70b533f7310ca (patch) | |
tree | 2ee00b986cbd13feaaa5b35f4f0d158f6c595194 /adb | |
parent | 10533c57ed6b3727d504f1936669f0035f1f9de4 (diff) | |
download | system_core-19dc2963057bda67f30adcfe1bf70b533f7310ca.tar.gz system_core-19dc2963057bda67f30adcfe1bf70b533f7310ca.tar.bz2 system_core-19dc2963057bda67f30adcfe1bf70b533f7310ca.zip |
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
Diffstat (limited to 'adb')
-rw-r--r-- | adb/daemon/usb.cpp | 25 |
1 files changed, 19 insertions, 6 deletions
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<void> 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<bool> stopped_; |