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

Commit 63fbd5ab authored by Andreas Huber's avatar Andreas Huber
Browse files

Apparently select() does not immediately return if one of the masked socket...

Apparently select() does not immediately return if one of the masked socket descriptors is closed... Stop relying on select for read-with-timeout functionality and use SO_RCVTIMEO socket option instead.

Change-Id: Ic2d4a8f5b6bbf16772fba39377809ec68d249c1f
related-to-bug: 2611257
parent 25dc5f30
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -39,6 +39,13 @@ status_t HTTPDataSource::connectWithRedirectsAndRange(off_t rangeStart) {

    int numRedirectsRemaining = 5;
    while (numRedirectsRemaining-- > 0) {
        {
            Mutex::Autolock autoLock(mStateLock);
            if (mState == DISCONNECTED) {
                return UNKNOWN_ERROR;
            }
        }

        status_t err = mHttp->connect(host.c_str(), port);

        if (err != OK) {
+7 −27
Original line number Diff line number Diff line
@@ -68,6 +68,11 @@ status_t HTTPStream::connect(const char *server, int port) {
        return UNKNOWN_ERROR;
    }

    struct timeval tv;
    tv.tv_usec = 0;
    tv.tv_sec = 5;
    CHECK_EQ(0, setsockopt(mSocket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)));

    mState = CONNECTING;

    int s = mSocket;
@@ -150,30 +155,6 @@ status_t HTTPStream::send(const char *data) {
    return send(data, strlen(data));
}

static ssize_t recvWithTimeout(
        int s, void *data, size_t size) {
    fd_set rs, es;
    FD_ZERO(&rs);
    FD_ZERO(&es);
    FD_SET(s, &rs);
    FD_SET(s, &es);

    struct timeval tv;
    tv.tv_sec = 5;  // 5 sec timeout
    tv.tv_usec = 0;

    int res = select(s + 1, &rs, NULL, &es, &tv);

    if (res < 0) {
        return -1;
    } else if (res == 0) {
        errno = ETIMEDOUT;
        return -1;
    }

    return recv(s, data, size, 0);
}

// A certain application spawns a local webserver that sends invalid responses,
// specifically it terminates header line with only a newline instead of the
// CRLF (carriage-return followed by newline) required by the HTTP specs.
@@ -192,7 +173,7 @@ status_t HTTPStream::receive_line(char *line, size_t size) {

    for (;;) {
        char c;
        ssize_t n = recvWithTimeout(mSocket, &c, 1);
        ssize_t n = recv(mSocket, &c, 1, 0);
        if (n < 0) {
            if (errno == EINTR) {
                continue;
@@ -310,8 +291,7 @@ status_t HTTPStream::receive_header(int *http_status) {
ssize_t HTTPStream::receive(void *data, size_t size) {
    size_t total = 0;
    while (total < size) {
        ssize_t n = recvWithTimeout(
                mSocket, (char *)data + total, size - total);
        ssize_t n = recv(mSocket, (char *)data + total, size - total, 0);

        if (n < 0) {
            if (errno == EINTR) {