Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1e2382a0 authored by Elliott Hughes's avatar Elliott Hughes Committed by Gerrit Code Review
Browse files

Merge "adb: fix adb client running out of sockets on Windows"

parents dd48ffe9 351ecd15
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -963,9 +963,11 @@ int handle_host_request(const char* service, TransportType type,
        fflush(stdout);
        SendOkay(reply_fd);

        // At least on Windows, if we exit() without shutdown(SD_SEND) or
        // closesocket(), the client's next recv() will error-out with
        // WSAECONNRESET and they'll never read the OKAY.
        // On Windows, if the process exits with open sockets that
        // shutdown(SD_SEND) has not been called on, TCP RST segments will be
        // sent to the peers which will cause their next recv() to error-out
        // with WSAECONNRESET. In the case of this code, that means the client
        // may not read the OKAY sent above.
        adb_shutdown(reply_fd);

        exit(0);
+7 −0
Original line number Diff line number Diff line
@@ -206,6 +206,7 @@ int adb_connect(const std::string& service, std::string* error) {
                return -1;
            }

            ReadOrderlyShutdown(fd);
            adb_close(fd);

            if (sscanf(&version_string[0], "%04x", &version) != 1) {
@@ -227,6 +228,7 @@ int adb_connect(const std::string& service, std::string* error) {
                   version, ADB_SERVER_VERSION);
            fd = _adb_connect("host:kill", error);
            if (fd >= 0) {
                ReadOrderlyShutdown(fd);
                adb_close(fd);
            } else {
                // If we couldn't connect to the server or had some other error,
@@ -271,6 +273,8 @@ bool adb_command(const std::string& service) {
        return false;
    }

    ReadOrderlyShutdown(fd);
    adb_close(fd);
    return true;
}

@@ -286,5 +290,8 @@ bool adb_query(const std::string& service, std::string* result, std::string* err
        adb_close(fd);
        return false;
    }

    ReadOrderlyShutdown(fd);
    adb_close(fd);
    return true;
}
+40 −0
Original line number Diff line number Diff line
@@ -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;
    }
}
+18 −0
Original line number Diff line number Diff line
@@ -41,6 +41,24 @@ bool ReadProtocolString(int fd, std::string* s, std::string* error);
// If this function fails, the contents of buf are undefined.
bool ReadFdExactly(int fd, void* buf, size_t len);

// Given a client socket, wait for orderly/graceful shutdown. Call this:
//
// * Before closing a client socket.
// * Only when no more data is expected to come in.
// * Only when the server is not waiting for data from the client (because then
//   the client and server will deadlock waiting for each other).
// * Only when the server is expected to close its socket right now.
// * Don't call shutdown(SHUT_WR) before calling this because that will shutdown
//   the client socket early, defeating the purpose of calling this.
//
// Waiting for orderly/graceful shutdown of the server socket will cause the
// server socket to close before the client socket. That prevents the client
// socket from staying in TIME_WAIT which eventually causes subsequent
// connect()s from the client to fail with WSAEADDRINUSE on Windows.
// Returns true if it is sure that orderly/graceful shutdown has occurred with
// no additional data read from the server.
bool ReadOrderlyShutdown(int fd);

// Writes exactly len bytes from buf to fd.
//
// Returns false if there is an error or if the fd was closed before the write
+3 −0
Original line number Diff line number Diff line
@@ -649,6 +649,7 @@ static int adb_download_buffer(const char *service, const char *fn, const void*
            std::string error;
            adb_status(fd, &error);
            fprintf(stderr,"* failed to write data '%s' *\n", error.c_str());
            adb_close(fd);
            return -1;
        }
        sz -= xfer;
@@ -664,6 +665,7 @@ static int adb_download_buffer(const char *service, const char *fn, const void*

    if (!adb_status(fd, &error)) {
        fprintf(stderr,"* error response '%s' *\n", error.c_str());
        adb_close(fd);
        return -1;
    }

@@ -1468,6 +1470,7 @@ int adb_commandline(int argc, const char **argv) {
        } else {
            // Successfully connected, kill command sent, okay status came back.
            // Server should exit() in a moment, if not already.
            ReadOrderlyShutdown(fd);
            adb_close(fd);
            return 0;
        }
Loading