adb: detect when the client disconnects in wait-for-device.

Avoid leaking a thread and its associated resources when a user cancels
wait-for-device.

Bug: http://b/26966721
Bug: https://code.google.com/p/android/issues/detail?id=199088
Change-Id: Idac80a24e9739ddd24e500fe14826a78f350c018
This commit is contained in:
Josh Gao 2016-02-19 10:42:40 -08:00
parent 022d447e9e
commit 09855472f4
2 changed files with 35 additions and 4 deletions

View file

@ -49,6 +49,7 @@
#include "remount_service.h"
#include "services.h"
#include "shell_service.h"
#include "sysdeps.h"
#include "transport.h"
struct stinfo {
@ -369,12 +370,21 @@ static void wait_for_state(int fd, void* data) {
std::string error = "unknown error";
const char* serial = sinfo->serial.length() ? sinfo->serial.c_str() : NULL;
atransport* t = acquire_one_transport(sinfo->transport_type, serial, &is_ambiguous, &error);
if (t != nullptr && t->connection_state == sinfo->state) {
SendOkay(fd);
break;
} else if (!is_ambiguous) {
adb_sleep_ms(1000);
adb_pollfd pfd = {.fd = fd, .events = POLLIN };
int rc = adb_poll(&pfd, 1, 1000);
if (rc < 0) {
SendFail(fd, error);
break;
} else if (rc > 0 && (pfd.revents & POLLHUP) != 0) {
// The other end of the socket is closed, probably because the other side was
// terminated, bail out.
break;
}
// Try again...
} else {
SendFail(fd, error);

View file

@ -112,8 +112,12 @@ class sysdeps_poll : public ::testing::Test {
}
void TearDown() override {
ASSERT_EQ(0, adb_close(fds[0]));
ASSERT_EQ(0, adb_close(fds[1]));
if (fds[0] >= 0) {
ASSERT_EQ(0, adb_close(fds[0]));
}
if (fds[1] >= 0) {
ASSERT_EQ(0, adb_close(fds[1]));
}
}
};
@ -190,3 +194,20 @@ TEST_F(sysdeps_poll, duplicate_fd) {
EXPECT_EQ(POLLRDNORM, pfd[0].revents);
EXPECT_EQ(POLLRDNORM, pfd[1].revents);
}
TEST_F(sysdeps_poll, disconnect) {
adb_pollfd pfd;
pfd.fd = fds[0];
pfd.events = POLLIN;
EXPECT_EQ(0, adb_poll(&pfd, 1, 0));
EXPECT_EQ(0, pfd.revents);
EXPECT_EQ(0, adb_close(fds[1]));
fds[1] = -1;
EXPECT_EQ(1, adb_poll(&pfd, 1, 100));
// Linux returns POLLIN | POLLHUP, Windows returns just POLLHUP.
EXPECT_EQ(POLLHUP, pfd.revents & POLLHUP);
}