adb: make fdevent_test, socket_test compile on Windows.

Switch pthread_* to use the adb_thread_* abstractions to allow the fdevent
and socket tests to compile on Win32.

Bug: http://b/27105824
Change-Id: I6541bb1398780b999837e701837d7f86a5eee8ca
diff --git a/adb/Android.mk b/adb/Android.mk
index 45646dc..5b1e3bb 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -59,6 +59,8 @@
 LIBADB_TEST_SRCS := \
     adb_io_test.cpp \
     adb_utils_test.cpp \
+    fdevent_test.cpp \
+    socket_test.cpp \
     sysdeps_test.cpp \
     transport_test.cpp \
 
@@ -87,14 +89,6 @@
     sysdeps_win32.cpp \
     usb_windows.cpp \
 
-LIBADB_TEST_linux_SRCS := \
-    fdevent_test.cpp \
-    socket_test.cpp \
-
-LIBADB_TEST_darwin_SRCS := \
-    fdevent_test.cpp \
-    socket_test.cpp \
-
 LIBADB_TEST_windows_SRCS := \
     sysdeps_win32_test.cpp \
 
diff --git a/adb/fdevent.cpp b/adb/fdevent.cpp
index 4617364..902548e 100644
--- a/adb/fdevent.cpp
+++ b/adb/fdevent.cpp
@@ -25,6 +25,7 @@
 #include <string.h>
 #include <unistd.h>
 
+#include <atomic>
 #include <list>
 #include <unordered_map>
 #include <vector>
@@ -70,6 +71,7 @@
 // That's why we don't need a lock for fdevent.
 static auto& g_poll_node_map = *new std::unordered_map<int, PollNode>();
 static auto& g_pending_list = *new std::list<fdevent*>();
+static std::atomic<bool> terminate_loop(false);
 static bool main_thread_valid;
 static unsigned long main_thread_id;
 
@@ -364,6 +366,10 @@
 #endif // !ADB_HOST
 
     while (true) {
+        if (terminate_loop) {
+            return;
+        }
+
         D("--- --- waiting for events");
 
         fdevent_process();
@@ -376,6 +382,10 @@
     }
 }
 
+void fdevent_terminate_loop() {
+    terminate_loop = true;
+}
+
 size_t fdevent_installed_count() {
     return g_poll_node_map.size();
 }
@@ -384,4 +394,5 @@
     g_poll_node_map.clear();
     g_pending_list.clear();
     main_thread_valid = false;
+    terminate_loop = false;
 }
diff --git a/adb/fdevent.h b/adb/fdevent.h
index 657fde5..207f9b7 100644
--- a/adb/fdevent.h
+++ b/adb/fdevent.h
@@ -76,9 +76,9 @@
 */
 void fdevent_loop();
 
-// For debugging only.
+// The following functions are used only for tests.
+void fdevent_terminate_loop();
 size_t fdevent_installed_count();
-// For debugging only.
 void fdevent_reset();
 
 #endif
diff --git a/adb/fdevent_test.cpp b/adb/fdevent_test.cpp
index 7fe3d37..c933ed5 100644
--- a/adb/fdevent_test.cpp
+++ b/adb/fdevent_test.cpp
@@ -18,15 +18,13 @@
 
 #include <gtest/gtest.h>
 
-#include <pthread.h>
-#include <signal.h>
-
 #include <limits>
 #include <queue>
 #include <string>
 #include <vector>
 
 #include "adb_io.h"
+#include "fdevent_test.h"
 
 class FdHandler {
   public:
@@ -48,7 +46,7 @@
         if (events & FDE_READ) {
             ASSERT_EQ(fd, handler->read_fd_);
             char c;
-            ASSERT_EQ(1, read(fd, &c, 1));
+            ASSERT_EQ(1, adb_read(fd, &c, 1));
             handler->queue_.push(c);
             fdevent_add(&handler->write_fde_, FDE_WRITE);
         }
@@ -57,7 +55,7 @@
             ASSERT_FALSE(handler->queue_.empty());
             char c = handler->queue_.front();
             handler->queue_.pop();
-            ASSERT_EQ(1, write(fd, &c, 1));
+            ASSERT_EQ(1, adb_write(fd, &c, 1));
             if (handler->queue_.empty()) {
               fdevent_del(&handler->write_fde_, FDE_WRITE);
             }
@@ -72,29 +70,19 @@
     std::queue<char> queue_;
 };
 
-static void signal_handler(int) {
-    pthread_exit(nullptr);
-}
-
-class FdeventTest : public ::testing::Test {
-  protected:
-    static void SetUpTestCase() {
-        ASSERT_NE(SIG_ERR, signal(SIGUSR1, signal_handler));
-        ASSERT_NE(SIG_ERR, signal(SIGPIPE, SIG_IGN));
-    }
-
-    virtual void SetUp() {
-        fdevent_reset();
-        ASSERT_EQ(0u, fdevent_installed_count());
-    }
-};
-
 struct ThreadArg {
     int first_read_fd;
     int last_write_fd;
     size_t middle_pipe_count;
 };
 
+TEST_F(FdeventTest, fdevent_terminate) {
+    adb_thread_t thread;
+    PrepareThread();
+    ASSERT_TRUE(adb_thread_create([](void*) { fdevent_loop(); }, nullptr, &thread));
+    TerminateThread(thread);
+}
+
 static void FdEventThreadFunc(ThreadArg* arg) {
     std::vector<int> read_fds;
     std::vector<int> write_fds;
@@ -102,7 +90,7 @@
     read_fds.push_back(arg->first_read_fd);
     for (size_t i = 0; i < arg->middle_pipe_count; ++i) {
         int fds[2];
-        ASSERT_EQ(0, pipe(fds));
+        ASSERT_EQ(0, adb_socketpair(fds));
         read_fds.push_back(fds[0]);
         write_fds.push_back(fds[1]);
     }
@@ -122,9 +110,9 @@
     const std::string MESSAGE = "fdevent_test";
     int fd_pair1[2];
     int fd_pair2[2];
-    ASSERT_EQ(0, pipe(fd_pair1));
-    ASSERT_EQ(0, pipe(fd_pair2));
-    pthread_t thread;
+    ASSERT_EQ(0, adb_socketpair(fd_pair1));
+    ASSERT_EQ(0, adb_socketpair(fd_pair2));
+    adb_thread_t thread;
     ThreadArg thread_arg;
     thread_arg.first_read_fd = fd_pair1[0];
     thread_arg.last_write_fd = fd_pair2[1];
@@ -132,9 +120,9 @@
     int writer = fd_pair1[1];
     int reader = fd_pair2[0];
 
-    ASSERT_EQ(0, pthread_create(&thread, nullptr,
-                                reinterpret_cast<void* (*)(void*)>(FdEventThreadFunc),
-                                &thread_arg));
+    PrepareThread();
+    ASSERT_TRUE(adb_thread_create(reinterpret_cast<void (*)(void*)>(FdEventThreadFunc), &thread_arg,
+                                  &thread));
 
     for (size_t i = 0; i < MESSAGE_LOOP_COUNT; ++i) {
         std::string read_buffer = MESSAGE;
@@ -144,10 +132,9 @@
         ASSERT_EQ(read_buffer, write_buffer);
     }
 
-    ASSERT_EQ(0, pthread_kill(thread, SIGUSR1));
-    ASSERT_EQ(0, pthread_join(thread, nullptr));
-    ASSERT_EQ(0, close(writer));
-    ASSERT_EQ(0, close(reader));
+    TerminateThread(thread);
+    ASSERT_EQ(0, adb_close(writer));
+    ASSERT_EQ(0, adb_close(reader));
 }
 
 struct InvalidFdArg {
@@ -161,7 +148,7 @@
     ASSERT_EQ(arg->expected_events, events);
     fdevent_remove(&arg->fde);
     if (++*(arg->happened_event_count) == 2) {
-        pthread_exit(nullptr);
+        fdevent_terminate_loop();
     }
 }
 
@@ -184,9 +171,7 @@
 }
 
 TEST_F(FdeventTest, invalid_fd) {
-    pthread_t thread;
-    ASSERT_EQ(0, pthread_create(&thread, nullptr,
-                                reinterpret_cast<void* (*)(void*)>(InvalidFdThreadFunc),
-                                nullptr));
-    ASSERT_EQ(0, pthread_join(thread, nullptr));
+    adb_thread_t thread;
+    ASSERT_TRUE(adb_thread_create(InvalidFdThreadFunc, nullptr, &thread));
+    ASSERT_TRUE(adb_thread_join(thread));
 }
diff --git a/adb/fdevent_test.h b/adb/fdevent_test.h
new file mode 100644
index 0000000..c853bce
--- /dev/null
+++ b/adb/fdevent_test.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "socket.h"
+#include "sysdeps.h"
+
+class FdeventTest : public ::testing::Test {
+  protected:
+    int dummy = -1;
+
+    static void SetUpTestCase() {
+#if !defined(_WIN32)
+        ASSERT_NE(SIG_ERR, signal(SIGPIPE, SIG_IGN));
+#endif
+    }
+
+    void SetUp() override {
+        fdevent_reset();
+        ASSERT_EQ(0u, fdevent_installed_count());
+    }
+
+    // Register a dummy socket used to wake up the fdevent loop to tell it to die.
+    void PrepareThread() {
+        int dummy_fds[2];
+        if (adb_socketpair(dummy_fds) != 0) {
+            FAIL() << "failed to create socketpair: " << strerror(errno);
+        }
+
+        asocket* dummy_socket = create_local_socket(dummy_fds[1]);
+        if (!dummy_socket) {
+            FAIL() << "failed to create local socket: " << strerror(errno);
+        }
+        dummy_socket->ready(dummy_socket);
+        dummy = dummy_fds[0];
+    }
+
+    void TerminateThread(adb_thread_t thread) {
+        fdevent_terminate_loop();
+        ASSERT_TRUE(WriteFdExactly(dummy, "", 1));
+        ASSERT_TRUE(adb_thread_join(thread));
+        ASSERT_EQ(0, adb_close(dummy));
+    }
+};
diff --git a/adb/socket_test.cpp b/adb/socket_test.cpp
index 03cab64..471ca09 100644
--- a/adb/socket_test.cpp
+++ b/adb/socket_test.cpp
@@ -18,119 +18,89 @@
 
 #include <gtest/gtest.h>
 
+#include <array>
 #include <limits>
 #include <queue>
 #include <string>
 #include <vector>
 
-#include <pthread.h>
-#include <signal.h>
 #include <unistd.h>
 
 #include "adb.h"
 #include "adb_io.h"
+#include "fdevent_test.h"
 #include "socket.h"
 #include "sysdeps.h"
 
-static void signal_handler(int) {
-    ASSERT_EQ(1u, fdevent_installed_count());
-    pthread_exit(nullptr);
-}
-
-// On host, register a dummy socket, so fdevet_loop() will not abort when previously
-// registered local sockets are all closed. On device, fdevent_subproc_setup() installs
-// one fdevent which can be considered as dummy socket.
-static void InstallDummySocket() {
-#if ADB_HOST
-    int dummy_fds[2];
-    ASSERT_EQ(0, pipe(dummy_fds));
-    asocket* dummy_socket = create_local_socket(dummy_fds[0]);
-    ASSERT_TRUE(dummy_socket != nullptr);
-    dummy_socket->ready(dummy_socket);
-#endif
-}
-
 struct ThreadArg {
     int first_read_fd;
     int last_write_fd;
     size_t middle_pipe_count;
 };
 
-static void FdEventThreadFunc(ThreadArg* arg) {
-    std::vector<int> read_fds;
-    std::vector<int> write_fds;
+class LocalSocketTest : public FdeventTest {};
 
-    read_fds.push_back(arg->first_read_fd);
-    for (size_t i = 0; i < arg->middle_pipe_count; ++i) {
-        int fds[2];
-        ASSERT_EQ(0, adb_socketpair(fds));
-        read_fds.push_back(fds[0]);
-        write_fds.push_back(fds[1]);
-    }
-    write_fds.push_back(arg->last_write_fd);
-
-    for (size_t i = 0; i < read_fds.size(); ++i) {
-        asocket* reader = create_local_socket(read_fds[i]);
-        ASSERT_TRUE(reader != nullptr);
-        asocket* writer = create_local_socket(write_fds[i]);
-        ASSERT_TRUE(writer != nullptr);
-        reader->peer = writer;
-        writer->peer = reader;
-        reader->ready(reader);
-    }
-
-    InstallDummySocket();
+static void FdEventThreadFunc(void*) {
     fdevent_loop();
 }
 
-class LocalSocketTest : public ::testing::Test {
-  protected:
-    static void SetUpTestCase() {
-        ASSERT_NE(SIG_ERR, signal(SIGUSR1, signal_handler));
-        ASSERT_NE(SIG_ERR, signal(SIGPIPE, SIG_IGN));
-    }
-
-    virtual void SetUp() {
-        fdevent_reset();
-        ASSERT_EQ(0u, fdevent_installed_count());
-    }
-};
-
 TEST_F(LocalSocketTest, smoke) {
-    const size_t PIPE_COUNT = 100;
-    const size_t MESSAGE_LOOP_COUNT = 100;
+    // Join two socketpairs with a chain of intermediate socketpairs.
+    int first[2];
+    std::vector<std::array<int, 2>> intermediates;
+    int last[2];
+
+    constexpr size_t INTERMEDIATE_COUNT = 50;
+    constexpr size_t MESSAGE_LOOP_COUNT = 100;
     const std::string MESSAGE = "socket_test";
-    int fd_pair1[2];
-    int fd_pair2[2];
-    ASSERT_EQ(0, adb_socketpair(fd_pair1));
-    ASSERT_EQ(0, adb_socketpair(fd_pair2));
-    pthread_t thread;
-    ThreadArg thread_arg;
-    thread_arg.first_read_fd = fd_pair1[0];
-    thread_arg.last_write_fd = fd_pair2[1];
-    thread_arg.middle_pipe_count = PIPE_COUNT;
-    int writer = fd_pair1[1];
-    int reader = fd_pair2[0];
 
-    ASSERT_EQ(0, pthread_create(&thread, nullptr,
-                                reinterpret_cast<void* (*)(void*)>(FdEventThreadFunc),
-                                &thread_arg));
+    intermediates.resize(INTERMEDIATE_COUNT);
+    ASSERT_EQ(0, adb_socketpair(first)) << strerror(errno);
+    ASSERT_EQ(0, adb_socketpair(last)) << strerror(errno);
+    asocket* prev_tail = create_local_socket(first[1]);
+    ASSERT_NE(nullptr, prev_tail);
 
-    usleep(1000);
+    auto connect = [](asocket* tail, asocket* head) {
+        tail->peer = head;
+        head->peer = tail;
+        tail->ready(tail);
+    };
+
+    for (auto& intermediate : intermediates) {
+        ASSERT_EQ(0, adb_socketpair(intermediate.data())) << strerror(errno);
+
+        asocket* head = create_local_socket(intermediate[0]);
+        ASSERT_NE(nullptr, head);
+
+        asocket* tail = create_local_socket(intermediate[1]);
+        ASSERT_NE(nullptr, tail);
+
+        connect(prev_tail, head);
+        prev_tail = tail;
+    }
+
+    asocket* end = create_local_socket(last[0]);
+    ASSERT_NE(nullptr, end);
+    connect(prev_tail, end);
+
+    PrepareThread();
+    adb_thread_t thread;
+    ASSERT_TRUE(adb_thread_create(FdEventThreadFunc, nullptr, &thread));
+
     for (size_t i = 0; i < MESSAGE_LOOP_COUNT; ++i) {
         std::string read_buffer = MESSAGE;
         std::string write_buffer(MESSAGE.size(), 'a');
-        ASSERT_TRUE(WriteFdExactly(writer, read_buffer.c_str(), read_buffer.size()));
-        ASSERT_TRUE(ReadFdExactly(reader, &write_buffer[0], write_buffer.size()));
+        ASSERT_TRUE(WriteFdExactly(first[0], &read_buffer[0], read_buffer.size()));
+        ASSERT_TRUE(ReadFdExactly(last[1], &write_buffer[0], write_buffer.size()));
         ASSERT_EQ(read_buffer, write_buffer);
     }
-    ASSERT_EQ(0, adb_close(writer));
-    ASSERT_EQ(0, adb_close(reader));
-    // Wait until the local sockets are closed.
-    sleep(1);
 
-    ASSERT_EQ(0, pthread_kill(thread, SIGUSR1));
-    ASSERT_EQ(0, pthread_join(thread, nullptr));
+    ASSERT_EQ(0, adb_close(first[0]));
+    ASSERT_EQ(0, adb_close(last[1]));
+
+    // Wait until the local sockets are closed.
+    adb_sleep_ms(100);
+    TerminateThread(thread);
 }
 
 struct CloseWithPacketArg {
@@ -160,7 +130,6 @@
     s->peer = cause_close_s;
     cause_close_s->ready(cause_close_s);
 
-    InstallDummySocket();
     fdevent_loop();
 }
 
@@ -176,21 +145,19 @@
     CloseWithPacketArg arg;
     arg.socket_fd = socket_fd[1];
     arg.cause_close_fd = cause_close_fd[1];
-    pthread_t thread;
-    ASSERT_EQ(0, pthread_create(&thread, nullptr,
-                                reinterpret_cast<void* (*)(void*)>(CloseWithPacketThreadFunc),
-                                &arg));
-    // Wait until the fdevent_loop() starts.
-    sleep(1);
-    ASSERT_EQ(0, adb_close(cause_close_fd[0]));
-    sleep(1);
-    ASSERT_EQ(2u, fdevent_installed_count());
-    ASSERT_EQ(0, adb_close(socket_fd[0]));
-    // Wait until the socket is closed.
-    sleep(1);
 
-    ASSERT_EQ(0, pthread_kill(thread, SIGUSR1));
-    ASSERT_EQ(0, pthread_join(thread, nullptr));
+    PrepareThread();
+    adb_thread_t thread;
+    ASSERT_TRUE(adb_thread_create(reinterpret_cast<void (*)(void*)>(CloseWithPacketThreadFunc),
+                                  &arg, &thread));
+    // Wait until the fdevent_loop() starts.
+    adb_sleep_ms(100);
+    ASSERT_EQ(0, adb_close(cause_close_fd[0]));
+    adb_sleep_ms(100);
+    EXPECT_EQ(2u, fdevent_installed_count());
+    ASSERT_EQ(0, adb_close(socket_fd[0]));
+
+    TerminateThread(thread);
 }
 
 // This test checks if we can read packets from a closing local socket.
@@ -203,26 +170,23 @@
     arg.socket_fd = socket_fd[1];
     arg.cause_close_fd = cause_close_fd[1];
 
-    pthread_t thread;
-    ASSERT_EQ(0, pthread_create(&thread, nullptr,
-                                reinterpret_cast<void* (*)(void*)>(CloseWithPacketThreadFunc),
-                                &arg));
+    PrepareThread();
+    adb_thread_t thread;
+    ASSERT_TRUE(adb_thread_create(reinterpret_cast<void (*)(void*)>(CloseWithPacketThreadFunc),
+                                  &arg, &thread));
     // Wait until the fdevent_loop() starts.
-    sleep(1);
+    adb_sleep_ms(100);
     ASSERT_EQ(0, adb_close(cause_close_fd[0]));
-    sleep(1);
-    ASSERT_EQ(2u, fdevent_installed_count());
+    adb_sleep_ms(100);
+    EXPECT_EQ(2u, fdevent_installed_count());
 
     // Verify if we can read successfully.
     std::vector<char> buf(arg.bytes_written);
+    ASSERT_NE(0u, arg.bytes_written);
     ASSERT_EQ(true, ReadFdExactly(socket_fd[0], buf.data(), buf.size()));
     ASSERT_EQ(0, adb_close(socket_fd[0]));
 
-    // Wait until the socket is closed.
-    sleep(1);
-
-    ASSERT_EQ(0, pthread_kill(thread, SIGUSR1));
-    ASSERT_EQ(0, pthread_join(thread, nullptr));
+    TerminateThread(thread);
 }
 
 // This test checks if we can close local socket in the following situation:
@@ -238,20 +202,17 @@
     arg.socket_fd = socket_fd[1];
     arg.cause_close_fd = cause_close_fd[1];
 
-    pthread_t thread;
-    ASSERT_EQ(0, pthread_create(&thread, nullptr,
-                                reinterpret_cast<void* (*)(void*)>(CloseWithPacketThreadFunc),
-                                &arg));
+    PrepareThread();
+    adb_thread_t thread;
+    ASSERT_TRUE(adb_thread_create(reinterpret_cast<void (*)(void*)>(CloseWithPacketThreadFunc),
+                                  &arg, &thread));
+
     // Wait until the fdevent_loop() starts.
-    sleep(1);
-    ASSERT_EQ(3u, fdevent_installed_count());
+    adb_sleep_ms(100);
+    EXPECT_EQ(3u, fdevent_installed_count());
     ASSERT_EQ(0, adb_close(socket_fd[0]));
 
-    // Wait until the socket is closed.
-    sleep(1);
-
-    ASSERT_EQ(0, pthread_kill(thread, SIGUSR1));
-    ASSERT_EQ(0, pthread_join(thread, nullptr));
+    TerminateThread(thread);
 }
 
 #if defined(__linux__)
@@ -260,50 +221,52 @@
     std::string error;
     int fd = network_loopback_client(5038, SOCK_STREAM, &error);
     ASSERT_GE(fd, 0) << error;
-    sleep(2);
+    adb_sleep_ms(200);
     ASSERT_EQ(0, adb_close(fd));
 }
 
 struct CloseRdHupSocketArg {
-  int socket_fd;
+    int socket_fd;
 };
 
 static void CloseRdHupSocketThreadFunc(CloseRdHupSocketArg* arg) {
-  asocket* s = create_local_socket(arg->socket_fd);
-  ASSERT_TRUE(s != nullptr);
+    asocket* s = create_local_socket(arg->socket_fd);
+    ASSERT_TRUE(s != nullptr);
 
-  InstallDummySocket();
-  fdevent_loop();
+    fdevent_loop();
 }
 
 // This test checks if we can close sockets in CLOSE_WAIT state.
 TEST_F(LocalSocketTest, close_socket_in_CLOSE_WAIT_state) {
-  std::string error;
-  int listen_fd = network_inaddr_any_server(5038, SOCK_STREAM, &error);
-  ASSERT_GE(listen_fd, 0);
-  pthread_t client_thread;
-  ASSERT_EQ(0, pthread_create(&client_thread, nullptr,
-                              reinterpret_cast<void* (*)(void*)>(ClientThreadFunc), nullptr));
+    std::string error;
+    int listen_fd = network_inaddr_any_server(5038, SOCK_STREAM, &error);
+    ASSERT_GE(listen_fd, 0);
 
-  struct sockaddr addr;
-  socklen_t alen;
-  alen = sizeof(addr);
-  int accept_fd = adb_socket_accept(listen_fd, &addr, &alen);
-  ASSERT_GE(accept_fd, 0);
-  CloseRdHupSocketArg arg;
-  arg.socket_fd = accept_fd;
-  pthread_t thread;
-  ASSERT_EQ(0, pthread_create(&thread, nullptr,
-                              reinterpret_cast<void* (*)(void*)>(CloseRdHupSocketThreadFunc),
-                              &arg));
-  // Wait until the fdevent_loop() starts.
-  sleep(1);
-  ASSERT_EQ(2u, fdevent_installed_count());
-  // Wait until the client closes its socket.
-  ASSERT_EQ(0, pthread_join(client_thread, nullptr));
-  sleep(2);
-  ASSERT_EQ(0, pthread_kill(thread, SIGUSR1));
-  ASSERT_EQ(0, pthread_join(thread, nullptr));
+    adb_thread_t client_thread;
+    ASSERT_TRUE(adb_thread_create(reinterpret_cast<void (*)(void*)>(ClientThreadFunc), nullptr,
+                                  &client_thread));
+
+    struct sockaddr addr;
+    socklen_t alen;
+    alen = sizeof(addr);
+    int accept_fd = adb_socket_accept(listen_fd, &addr, &alen);
+    ASSERT_GE(accept_fd, 0);
+    CloseRdHupSocketArg arg;
+    arg.socket_fd = accept_fd;
+
+    PrepareThread();
+    adb_thread_t thread;
+    ASSERT_TRUE(adb_thread_create(reinterpret_cast<void (*)(void*)>(CloseRdHupSocketThreadFunc),
+                                  &arg, &thread));
+
+    // Wait until the fdevent_loop() starts.
+    adb_sleep_ms(100);
+    EXPECT_EQ(2u, fdevent_installed_count());
+
+    // Wait until the client closes its socket.
+    ASSERT_TRUE(adb_thread_join(client_thread));
+
+    TerminateThread(thread);
 }
 
 #endif  // defined(__linux__)