summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Andres Klode <julian.klode@canonical.com>2020-06-29 14:03:21 +0200
committerJulian Andres Klode <julian.klode@canonical.com>2020-07-24 16:30:43 +0200
commit08f05aa8beb58fa32485e2087eb21a9f3cb267bb (patch)
treedde4a2905ce37b365fe6c6dc4c5afe4761b27bdc
parentc2cb8abbf5d8a49b25071ffffca93a083fe725fc (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.cc18
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)