Loading adb/adb.h +0 −4 Original line number Diff line number Diff line Loading @@ -196,10 +196,6 @@ ConnectionState connection_state(atransport* t); extern const char* adb_device_banner; #if !ADB_HOST extern int SHELL_EXIT_NOTIFY_FD; #endif // !ADB_HOST #define CHUNK_SIZE (64 * 1024) #if !ADB_HOST Loading adb/daemon/shell_service.cpp +0 −16 Original line number Diff line number Diff line Loading @@ -681,22 +681,6 @@ void Subprocess::WaitForExit() { } protocol_sfd_.reset(-1); } // Pass the local socket FD to the shell cleanup fdevent. if (SHELL_EXIT_NOTIFY_FD >= 0) { int fd = local_socket_sfd_; if (WriteFdExactly(SHELL_EXIT_NOTIFY_FD, &fd, sizeof(fd))) { D("passed fd %d to SHELL_EXIT_NOTIFY_FD (%d) for pid %d", fd, SHELL_EXIT_NOTIFY_FD, pid_); // The shell exit fdevent now owns the FD and will close it once // the last bit of data flushes through. static_cast<void>(local_socket_sfd_.release()); } else { PLOG(ERROR) << "failed to write fd " << fd << " to SHELL_EXIT_NOTIFY_FD (" << SHELL_EXIT_NOTIFY_FD << ") for pid " << pid_; } } } } // namespace Loading adb/daemon/shell_service_test.cpp +0 −20 Original line number Diff line number Diff line Loading @@ -55,40 +55,20 @@ class ShellServiceTest : public ::testing::Test { static sighandler_t saved_sigpipe_handler_; int subprocess_fd_ = -1; int shell_exit_receiver_fd_ = -1, saved_shell_exit_fd_; }; sighandler_t ShellServiceTest::saved_sigpipe_handler_ = nullptr; void ShellServiceTest::StartTestSubprocess( const char* command, SubprocessType type, SubprocessProtocol protocol) { // We want to intercept the shell exit message to make sure it's sent. saved_shell_exit_fd_ = SHELL_EXIT_NOTIFY_FD; int fd[2]; ASSERT_TRUE(adb_socketpair(fd) >= 0); SHELL_EXIT_NOTIFY_FD = fd[0]; shell_exit_receiver_fd_ = fd[1]; subprocess_fd_ = StartSubprocess(command, nullptr, type, protocol); ASSERT_TRUE(subprocess_fd_ >= 0); } void ShellServiceTest::CleanupTestSubprocess() { if (subprocess_fd_ >= 0) { // Subprocess should send its FD to SHELL_EXIT_NOTIFY_FD for cleanup. int notified_fd = -1; ASSERT_TRUE(ReadFdExactly(shell_exit_receiver_fd_, ¬ified_fd, sizeof(notified_fd))); ASSERT_EQ(notified_fd, subprocess_fd_); adb_close(subprocess_fd_); subprocess_fd_ = -1; // Restore SHELL_EXIT_NOTIFY_FD. adb_close(SHELL_EXIT_NOTIFY_FD); adb_close(shell_exit_receiver_fd_); shell_exit_receiver_fd_ = -1; SHELL_EXIT_NOTIFY_FD = saved_shell_exit_fd_; } } Loading adb/fdevent.cpp +10 −77 Original line number Diff line number Diff line Loading @@ -44,13 +44,6 @@ #include "adb_unique_fd.h" #include "adb_utils.h" #if !ADB_HOST // This socket is used when a subproc shell service exists. // It wakes up the fdevent_loop() and cause the correct handling // of the shell's pseudo-tty master. I.e. force close it. int SHELL_EXIT_NOTIFY_FD = -1; #endif // !ADB_HOST #define FDE_EVENTMASK 0x00ff #define FDE_STATEMASK 0xff00 Loading Loading @@ -296,72 +289,6 @@ static void fdevent_call_fdfunc(fdevent* fde) { fde->func(fde->fd, events, fde->arg); } #if !ADB_HOST #include <sys/ioctl.h> static void fdevent_subproc_event_func(int fd, unsigned ev, void* /* userdata */) { D("subproc handling on fd = %d, ev = %x", fd, ev); CHECK_GE(fd, 0); if (ev & FDE_READ) { int subproc_fd; if(!ReadFdExactly(fd, &subproc_fd, sizeof(subproc_fd))) { LOG(FATAL) << "Failed to read the subproc's fd from " << fd; } auto it = g_poll_node_map.find(subproc_fd); if (it == g_poll_node_map.end()) { D("subproc_fd %d cleared from fd_table", subproc_fd); adb_close(subproc_fd); return; } fdevent* subproc_fde = it->second.fde; if(subproc_fde->fd != subproc_fd) { // Already reallocated? LOG(FATAL) << "subproc_fd(" << subproc_fd << ") != subproc_fde->fd(" << subproc_fde->fd << ")"; return; } subproc_fde->force_eof = 1; int rcount = 0; ioctl(subproc_fd, FIONREAD, &rcount); D("subproc with fd %d has rcount=%d, err=%d", subproc_fd, rcount, errno); if (rcount != 0) { // If there is data left, it will show up in the select(). // This works because there is no other thread reading that // data when in this fd_func(). return; } D("subproc_fde %s", dump_fde(subproc_fde).c_str()); subproc_fde->events |= FDE_READ; if(subproc_fde->state & FDE_PENDING) { return; } subproc_fde->state |= FDE_PENDING; fdevent_call_fdfunc(subproc_fde); } } static void fdevent_subproc_setup() { int s[2]; if(adb_socketpair(s)) { PLOG(FATAL) << "cannot create shell-exit socket-pair"; } D("fdevent_subproc: socket pair (%d, %d)", s[0], s[1]); SHELL_EXIT_NOTIFY_FD = s[0]; fdevent *fde = fdevent_create(s[1], fdevent_subproc_event_func, NULL); CHECK(fde != nullptr) << "cannot create fdevent for shell-exit handler"; fdevent_add(fde, FDE_READ); } #endif // !ADB_HOST static void fdevent_run_flush() EXCLUDES(run_queue_mutex) { // We need to be careful around reentrancy here, since a function we call can queue up another // function. Loading Loading @@ -402,6 +329,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); Loading @@ -418,7 +349,12 @@ void fdevent_run_on_main_thread(std::function<void()> 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"; } } Loading @@ -426,9 +362,6 @@ void fdevent_run_on_main_thread(std::function<void()> fn) { void fdevent_loop() { set_main_thread(); #if !ADB_HOST fdevent_subproc_setup(); #endif // !ADB_HOST fdevent_run_setup(); while (true) { Loading adb/fdevent_test.cpp +9 −3 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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]); } } Loading Loading
adb/adb.h +0 −4 Original line number Diff line number Diff line Loading @@ -196,10 +196,6 @@ ConnectionState connection_state(atransport* t); extern const char* adb_device_banner; #if !ADB_HOST extern int SHELL_EXIT_NOTIFY_FD; #endif // !ADB_HOST #define CHUNK_SIZE (64 * 1024) #if !ADB_HOST Loading
adb/daemon/shell_service.cpp +0 −16 Original line number Diff line number Diff line Loading @@ -681,22 +681,6 @@ void Subprocess::WaitForExit() { } protocol_sfd_.reset(-1); } // Pass the local socket FD to the shell cleanup fdevent. if (SHELL_EXIT_NOTIFY_FD >= 0) { int fd = local_socket_sfd_; if (WriteFdExactly(SHELL_EXIT_NOTIFY_FD, &fd, sizeof(fd))) { D("passed fd %d to SHELL_EXIT_NOTIFY_FD (%d) for pid %d", fd, SHELL_EXIT_NOTIFY_FD, pid_); // The shell exit fdevent now owns the FD and will close it once // the last bit of data flushes through. static_cast<void>(local_socket_sfd_.release()); } else { PLOG(ERROR) << "failed to write fd " << fd << " to SHELL_EXIT_NOTIFY_FD (" << SHELL_EXIT_NOTIFY_FD << ") for pid " << pid_; } } } } // namespace Loading
adb/daemon/shell_service_test.cpp +0 −20 Original line number Diff line number Diff line Loading @@ -55,40 +55,20 @@ class ShellServiceTest : public ::testing::Test { static sighandler_t saved_sigpipe_handler_; int subprocess_fd_ = -1; int shell_exit_receiver_fd_ = -1, saved_shell_exit_fd_; }; sighandler_t ShellServiceTest::saved_sigpipe_handler_ = nullptr; void ShellServiceTest::StartTestSubprocess( const char* command, SubprocessType type, SubprocessProtocol protocol) { // We want to intercept the shell exit message to make sure it's sent. saved_shell_exit_fd_ = SHELL_EXIT_NOTIFY_FD; int fd[2]; ASSERT_TRUE(adb_socketpair(fd) >= 0); SHELL_EXIT_NOTIFY_FD = fd[0]; shell_exit_receiver_fd_ = fd[1]; subprocess_fd_ = StartSubprocess(command, nullptr, type, protocol); ASSERT_TRUE(subprocess_fd_ >= 0); } void ShellServiceTest::CleanupTestSubprocess() { if (subprocess_fd_ >= 0) { // Subprocess should send its FD to SHELL_EXIT_NOTIFY_FD for cleanup. int notified_fd = -1; ASSERT_TRUE(ReadFdExactly(shell_exit_receiver_fd_, ¬ified_fd, sizeof(notified_fd))); ASSERT_EQ(notified_fd, subprocess_fd_); adb_close(subprocess_fd_); subprocess_fd_ = -1; // Restore SHELL_EXIT_NOTIFY_FD. adb_close(SHELL_EXIT_NOTIFY_FD); adb_close(shell_exit_receiver_fd_); shell_exit_receiver_fd_ = -1; SHELL_EXIT_NOTIFY_FD = saved_shell_exit_fd_; } } Loading
adb/fdevent.cpp +10 −77 Original line number Diff line number Diff line Loading @@ -44,13 +44,6 @@ #include "adb_unique_fd.h" #include "adb_utils.h" #if !ADB_HOST // This socket is used when a subproc shell service exists. // It wakes up the fdevent_loop() and cause the correct handling // of the shell's pseudo-tty master. I.e. force close it. int SHELL_EXIT_NOTIFY_FD = -1; #endif // !ADB_HOST #define FDE_EVENTMASK 0x00ff #define FDE_STATEMASK 0xff00 Loading Loading @@ -296,72 +289,6 @@ static void fdevent_call_fdfunc(fdevent* fde) { fde->func(fde->fd, events, fde->arg); } #if !ADB_HOST #include <sys/ioctl.h> static void fdevent_subproc_event_func(int fd, unsigned ev, void* /* userdata */) { D("subproc handling on fd = %d, ev = %x", fd, ev); CHECK_GE(fd, 0); if (ev & FDE_READ) { int subproc_fd; if(!ReadFdExactly(fd, &subproc_fd, sizeof(subproc_fd))) { LOG(FATAL) << "Failed to read the subproc's fd from " << fd; } auto it = g_poll_node_map.find(subproc_fd); if (it == g_poll_node_map.end()) { D("subproc_fd %d cleared from fd_table", subproc_fd); adb_close(subproc_fd); return; } fdevent* subproc_fde = it->second.fde; if(subproc_fde->fd != subproc_fd) { // Already reallocated? LOG(FATAL) << "subproc_fd(" << subproc_fd << ") != subproc_fde->fd(" << subproc_fde->fd << ")"; return; } subproc_fde->force_eof = 1; int rcount = 0; ioctl(subproc_fd, FIONREAD, &rcount); D("subproc with fd %d has rcount=%d, err=%d", subproc_fd, rcount, errno); if (rcount != 0) { // If there is data left, it will show up in the select(). // This works because there is no other thread reading that // data when in this fd_func(). return; } D("subproc_fde %s", dump_fde(subproc_fde).c_str()); subproc_fde->events |= FDE_READ; if(subproc_fde->state & FDE_PENDING) { return; } subproc_fde->state |= FDE_PENDING; fdevent_call_fdfunc(subproc_fde); } } static void fdevent_subproc_setup() { int s[2]; if(adb_socketpair(s)) { PLOG(FATAL) << "cannot create shell-exit socket-pair"; } D("fdevent_subproc: socket pair (%d, %d)", s[0], s[1]); SHELL_EXIT_NOTIFY_FD = s[0]; fdevent *fde = fdevent_create(s[1], fdevent_subproc_event_func, NULL); CHECK(fde != nullptr) << "cannot create fdevent for shell-exit handler"; fdevent_add(fde, FDE_READ); } #endif // !ADB_HOST static void fdevent_run_flush() EXCLUDES(run_queue_mutex) { // We need to be careful around reentrancy here, since a function we call can queue up another // function. Loading Loading @@ -402,6 +329,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); Loading @@ -418,7 +349,12 @@ void fdevent_run_on_main_thread(std::function<void()> 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"; } } Loading @@ -426,9 +362,6 @@ void fdevent_run_on_main_thread(std::function<void()> fn) { void fdevent_loop() { set_main_thread(); #if !ADB_HOST fdevent_subproc_setup(); #endif // !ADB_HOST fdevent_run_setup(); while (true) { Loading
adb/fdevent_test.cpp +9 −3 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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]); } } Loading