diff options
author | Julian Andres Klode <julian.klode@canonical.com> | 2020-06-29 14:03:21 +0200 |
---|---|---|
committer | Julian Andres Klode <julian.klode@canonical.com> | 2020-07-24 16:30:43 +0200 |
commit | 08f05aa8beb58fa32485e2087eb21a9f3cb267bb (patch) | |
tree | dde4a2905ce37b365fe6c6dc4c5afe4761b27bdc | |
parent | c2cb8abbf5d8a49b25071ffffca93a083fe725fc (diff) |
http: Redesign reading of pending data
Instead of reading the data early, disable the timeout for the
select() call and read the data later. Also, change Read() to
call only once to drain the buffer in such instances.
We could optimize this to call read() multiple times if there
is also pending stuff on the socket, but that it slightly more
complex and should not provide any benefits.
-rw-r--r-- | methods/http.cc | 18 |
1 files changed, 8 insertions, 10 deletions
diff --git a/methods/http.cc b/methods/http.cc index c8aeea1ad..9cfc91330 100644 --- a/methods/http.cc +++ b/methods/http.cc @@ -783,13 +783,11 @@ ResultState HttpServerState::Go(bool ToFile, RequestState &Req) ToFile == false)) return ResultState::TRANSIENT_ERROR; - // Handle server IO - if (ServerFd->HasPending() && In.ReadSpace() == true) - { - errno = 0; - if (In.Read(ServerFd) == false) - return Die(Req); - } + // Record if we have data pending to read in the server, so that we can + // skip the wait in select(). This can happen if data has already been + // read into a methodfd's buffer - the TCP queue might be empty at that + // point. + bool ServerPending = ServerFd->HasPending(); fd_set rfds,wfds; FD_ZERO(&rfds); @@ -821,7 +819,7 @@ ResultState HttpServerState::Go(bool ToFile, RequestState &Req) // Select struct timeval tv; - tv.tv_sec = TimeOut; + tv.tv_sec = ServerPending ? 0 : TimeOut; tv.tv_usec = 0; int Res = 0; if ((Res = select(MaxFd+1,&rfds,&wfds,0,&tv)) < 0) @@ -832,14 +830,14 @@ ResultState HttpServerState::Go(bool ToFile, RequestState &Req) return ResultState::TRANSIENT_ERROR; } - if (Res == 0) + if (Res == 0 && not ServerPending) { _error->Error(_("Connection timed out")); return ResultState::TRANSIENT_ERROR; } // Handle server IO - if (ServerFd->Fd() != -1 && FD_ISSET(ServerFd->Fd(), &rfds)) + if (ServerPending || (ServerFd->Fd() != -1 && FD_ISSET(ServerFd->Fd(), &rfds))) { errno = 0; if (In.Read(ServerFd) == false) |