summaryrefslogtreecommitdiffstats
path: root/adb/adb_io.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'adb/adb_io.cpp')
-rw-r--r--adb/adb_io.cpp40
1 files changed, 40 insertions, 0 deletions
diff --git a/adb/adb_io.cpp b/adb/adb_io.cpp
index 7788996ab..a37fbc086 100644
--- a/adb/adb_io.cpp
+++ b/adb/adb_io.cpp
@@ -137,3 +137,43 @@ bool WriteFdFmt(int fd, const char* fmt, ...) {
return WriteFdExactly(fd, str);
}
+
+bool ReadOrderlyShutdown(int fd) {
+ char buf[16];
+
+ // Only call this function if you're sure that the peer does
+ // orderly/graceful shutdown of the socket, closing the socket so that
+ // adb_read() will return 0. If the peer keeps the socket open, adb_read()
+ // will never return.
+ int result = adb_read(fd, buf, sizeof(buf));
+ if (result == -1) {
+ // If errno is EAGAIN, that means this function was called on a
+ // nonblocking socket and it would have blocked (which would be bad
+ // because we'd probably block the main thread where nonblocking IO is
+ // done). Don't do that. If you have a nonblocking socket, use the
+ // fdevent APIs to get called on FDE_READ, and then call this function
+ // if you really need to, but it shouldn't be needed for server sockets.
+ CHECK_NE(errno, EAGAIN);
+
+ // Note that on Windows, orderly shutdown sometimes causes
+ // recv() == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET. That
+ // can be ignored.
+ return false;
+ } else if (result == 0) {
+ // Peer has performed an orderly/graceful shutdown.
+ return true;
+ } else {
+ // Unexpectedly received data. This is essentially a protocol error
+ // because you should not call this function unless you expect no more
+ // data. We don't repeatedly call adb_read() until we get zero because
+ // we don't know how long that would take, but we do know that the
+ // caller wants to close the socket soon.
+ VLOG(RWX) << "ReadOrderlyShutdown(" << fd << ") unexpectedly read "
+ << dump_hex(buf, result);
+ // Shutdown the socket to prevent the caller from reading or writing to
+ // it which doesn't make sense if we just read and discarded some data.
+ adb_shutdown(fd);
+ errno = EINVAL;
+ return false;
+ }
+}