diff --git a/adb/fdevent.cpp b/adb/fdevent.cpp index ba82e7c5f..f3b8ef5ca 100644 --- a/adb/fdevent.cpp +++ b/adb/fdevent.cpp @@ -402,6 +402,10 @@ static void fdevent_run_setup() { PLOG(FATAL) << "failed to create run queue notify socketpair"; } + if (!set_file_block_mode(s[0], false) || !set_file_block_mode(s[1], false)) { + PLOG(FATAL) << "failed to make run queue notify socket nonblocking"; + } + run_queue_notify_fd.reset(s[0]); fdevent* fde = fdevent_create(s[1], fdevent_run_func, nullptr); CHECK(fde != nullptr); @@ -418,7 +422,12 @@ void fdevent_run_on_main_thread(std::function fn) { // run_queue_notify_fd could still be -1 if we're called before fdevent has finished setting up. // In that case, rely on the setup code to flush the queue without a notification being needed. if (run_queue_notify_fd != -1) { - if (adb_write(run_queue_notify_fd.get(), "", 1) != 1) { + int rc = adb_write(run_queue_notify_fd.get(), "", 1); + + // It's possible that we get EAGAIN here, if lots of notifications came in while handling. + if (rc == 0) { + PLOG(FATAL) << "run queue notify fd was closed?"; + } else if (rc == -1 && errno != EAGAIN) { PLOG(FATAL) << "failed to write to run queue notify fd"; } } diff --git a/adb/fdevent_test.cpp b/adb/fdevent_test.cpp index dadae5ab7..95dc4c248 100644 --- a/adb/fdevent_test.cpp +++ b/adb/fdevent_test.cpp @@ -180,7 +180,13 @@ TEST_F(FdeventTest, run_on_main_thread) { PrepareThread(); std::thread thread(fdevent_loop); - for (int i = 0; i < 100; ++i) { + // Block the main thread for a long time while we queue our callbacks. + fdevent_run_on_main_thread([]() { + check_main_thread(); + std::this_thread::sleep_for(std::chrono::seconds(1)); + }); + + for (int i = 0; i < 1000000; ++i) { fdevent_run_on_main_thread([i, &vec]() { check_main_thread(); vec.push_back(i); @@ -189,8 +195,8 @@ TEST_F(FdeventTest, run_on_main_thread) { TerminateThread(thread); - ASSERT_EQ(100u, vec.size()); - for (int i = 0; i < 100; ++i) { + ASSERT_EQ(1000000u, vec.size()); + for (int i = 0; i < 1000000; ++i) { ASSERT_EQ(i, vec[i]); } }