From: Eduard Bagdasaryan Date: Mon, 9 Mar 2020 18:11:12 +0000 (+0000) Subject: Preserve caller context across tunnelDelayed*Read (#560) X-Git-Tag: SQUID_5_0_2~19 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c0b40a535e84323e89a3b93bec4c0a4c666c9eed;p=thirdparty%2Fsquid.git Preserve caller context across tunnelDelayed*Read (#560) tunnel.cc code approximates delay pools functionality using event.h API that is not meant for transaction-specific events. We (temporary) add a transaction context data member to TunnelStateData until the class switches to using transaction-specific deferred reads API. --- diff --git a/src/clients/HttpTunneler.cc b/src/clients/HttpTunneler.cc index 924d747ab9..fe05eb61aa 100644 --- a/src/clients/HttpTunneler.cc +++ b/src/clients/HttpTunneler.cc @@ -206,6 +206,7 @@ Http::Tunneler::handleReadyRead(const CommIoCbParams &io) #else rd.size = readBuf.spaceSize(); #endif + // XXX: defer read if rd.size <= 0 switch (Comm::ReadNow(rd, readBuf)) { case Comm::INPROGRESS: diff --git a/src/tunnel.cc b/src/tunnel.cc index 75e338d0ac..16caef596d 100644 --- a/src/tunnel.cc +++ b/src/tunnel.cc @@ -168,6 +168,8 @@ public: HappyConnOpenerPointer connOpener; ///< current connection opening job ResolvedPeersPointer destinations; ///< paths for forwarding the request bool destinationsFound; ///< At least one candidate path found + // TODO: remove after fixing deferred reads in TunnelStateData::copyRead() + CodeContext::Pointer codeContext; ///< our creator context // AsyncCalls which we set and may need cancelling. struct { @@ -318,7 +320,8 @@ TunnelStateData::TunnelStateData(ClientHttpRequest *clientRequest) : startTime(squid_curtime), waitingForConnectExchange(false), destinations(new ResolvedPeers()), - destinationsFound(false) + destinationsFound(false), + codeContext(CodeContext::Current()) { debugs(26, 3, "TunnelStateData constructed this=" << this); client.readPendingFunc = &tunnelDelayedClientRead; @@ -690,10 +693,13 @@ tunnelDelayedClientRead(void *data) return; TunnelStateData *tunnel = static_cast(data); + const auto savedContext = CodeContext::Current(); + CodeContext::Reset(tunnel->codeContext); tunnel->client.readPending = NULL; static uint64_t counter=0; debugs(26, 7, "Client read(2) delayed " << ++counter << " times"); tunnel->copyRead(tunnel->client, TunnelStateData::ReadClient); + CodeContext::Reset(savedContext); } static void @@ -703,10 +709,13 @@ tunnelDelayedServerRead(void *data) return; TunnelStateData *tunnel = static_cast(data); + const auto savedContext = CodeContext::Current(); + CodeContext::Reset(tunnel->codeContext); tunnel->server.readPending = NULL; static uint64_t counter=0; debugs(26, 7, "Server read(2) delayed " << ++counter << " times"); tunnel->copyRead(tunnel->server, TunnelStateData::ReadServer); + CodeContext::Reset(savedContext); } void @@ -717,6 +726,9 @@ TunnelStateData::copyRead(Connection &from, IOCB *completion) // then we schedule an event to try again in a few I/O cycles. // Allow at least 1 byte to be read every (0.3*10) seconds. int bw = from.bytesWanted(1, SQUID_TCP_SO_RCVBUF); + // XXX: Delay pools must not delay client-to-Squid traffic (i.e. when + // from.readPendingFunc is tunnelDelayedClientRead()). + // XXX: Bug #4913: Use DeferredRead instead. if (bw == 1 && ++from.delayedLoops < 10) { from.readPending = this; eventAdd("tunnelDelayedServerRead", from.readPendingFunc, from.readPending, 0.3, true);