diff options
author | Julian Andres Klode <jak@debian.org> | 2017-06-28 13:20:54 +0200 |
---|---|---|
committer | Julian Andres Klode <jak@debian.org> | 2017-06-28 15:52:38 +0200 |
commit | f806530b9ea858ca6bda8fb8f43d988aba02dab3 (patch) | |
tree | 23d237b5912c43ff6926c7d7d8e2f134cc90f4b4 | |
parent | 0fe2161020d6e331639ed11872a947dd20035890 (diff) |
methods: http: Drain pending data before selecting
GnuTLS can already have data pending in its buffers, we need
to to drain that first otherwise select() might block
indefinitely.
Gbp-Dch: ignore
-rw-r--r-- | methods/connect.cc | 9 | ||||
-rw-r--r-- | methods/connect.h | 2 | ||||
-rw-r--r-- | methods/http.cc | 10 |
3 files changed, 20 insertions, 1 deletions
diff --git a/methods/connect.cc b/methods/connect.cc index c40f34f2d..e48008214 100644 --- a/methods/connect.cc +++ b/methods/connect.cc @@ -98,6 +98,10 @@ struct FdFd : public MethodFd } }; +bool MethodFd::HasPending() +{ + return false; +} std::unique_ptr<MethodFd> MethodFd::FromFd(int iFd) { FdFd *fd = new FdFd(); @@ -626,6 +630,11 @@ struct TlsFd : public MethodFd return -1; return UnderlyingFd->Close(); } + + bool HasPending() APT_OVERRIDE + { + return gnutls_record_check_pending(session) > 0; + } }; bool UnwrapTLS(std::string Host, std::unique_ptr<MethodFd> &Fd, diff --git a/methods/connect.h b/methods/connect.h index 39f3c1ce2..4456d660d 100644 --- a/methods/connect.h +++ b/methods/connect.h @@ -35,6 +35,8 @@ struct MethodFd virtual ~MethodFd(){}; /// \brief Construct a MethodFd from a UNIX file descriptor static std::unique_ptr<MethodFd> FromFd(int iFd); + /// \brief If there is pending data. + virtual bool HasPending(); }; bool Connect(std::string To, int Port, const char *Service, int DefPort, diff --git a/methods/http.cc b/methods/http.cc index 4d8c0808b..b302c896d 100644 --- a/methods/http.cc +++ b/methods/http.cc @@ -621,7 +621,15 @@ bool HttpServerState::Go(bool ToFile, RequestState &Req) if (ServerFd->Fd() == -1 && (In.WriteSpace() == false || ToFile == false)) return false; - + + // Handle server IO + if (ServerFd->HasPending() && In.ReadSpace() == true) + { + errno = 0; + if (In.Read(ServerFd) == false) + return Die(Req); + } + fd_set rfds,wfds; FD_ZERO(&rfds); FD_ZERO(&wfds); |