Index: squid-3.3.13/src/forward.h
===================================================================
--- squid-3.3.13.orig/src/forward.h
+++ squid-3.3.13/src/forward.h
@@ -86,6 +86,9 @@ private:
     ErrorState *makeConnectingError(const err_type type) const;
     static void RegisterWithCacheManager(void);
 
+    /// stops monitoring server connection for closure and updates pconn stats
+    void closeServerConnection(const char *reason);
+
 public:
     StoreEntry *entry;
     HttpRequest *request;
@@ -116,6 +119,8 @@ private:
 
     Comm::ConnectionPointer serverConn; ///< a successfully opened connection to a server.
 
+    AsyncCall::Pointer closeHandler; ///< The serverConn close handler
+
     /// possible pconn race states
     typedef enum { raceImpossible, racePossible, raceHappened } PconnRace;
     PconnRace pconnRace; ///< current pconn race state
Index: squid-3.3.13/src/forward.cc
===================================================================
--- squid-3.3.13.orig/src/forward.cc
+++ squid-3.3.13/src/forward.cc
@@ -102,10 +102,7 @@ FwdState::abort(void* d)
     Pointer tmp = fwd; // Grab a temporary pointer to keep the object alive during our scope.
 
     if (Comm::IsConnOpen(fwd->serverConnection())) {
-        comm_remove_close_handler(fwd->serverConnection()->fd, fwdServerClosedWrapper, fwd);
-        debugs(17, 3, HERE << "store entry aborted; closing " <<
-               fwd->serverConnection());
-        fwd->serverConnection()->close();
+        fwd->closeServerConnection("store entry aborted");
     } else {
         debugs(17, 7, HERE << "store entry aborted; no connection to close");
     }
@@ -113,6 +110,16 @@ FwdState::abort(void* d)
     fwd->self = NULL;
 }
 
+void
+FwdState::closeServerConnection(const char *reason)
+{
+    debugs(17, 3, "because " << reason << "; " << serverConn);
+    comm_remove_close_handler(serverConn->fd, closeHandler);
+    closeHandler = NULL;
+    fwdPconnPool->noteUses(fd_table[serverConn->fd].pconn.uses);
+    serverConn->close();
+}
+
 /**** PUBLIC INTERFACE ********************************************************/
 
 FwdState::FwdState(const Comm::ConnectionPointer &client, StoreEntry * e, HttpRequest * r, const AccessLogEntryPointer &alp):
@@ -268,9 +275,7 @@ FwdState::~FwdState()
     }
 
     if (Comm::IsConnOpen(serverConn)) {
-        comm_remove_close_handler(serverConnection()->fd, fwdServerClosedWrapper, this);
-        debugs(17, 3, HERE << "closing FD " << serverConnection()->fd);
-        serverConn->close();
+        closeServerConnection(__FUNCTION__);
     }
 
     serverDestinations.clean();
@@ -426,7 +431,8 @@ FwdState::unregister(Comm::ConnectionPoi
     debugs(17, 3, HERE << entry->url() );
     assert(serverConnection() == conn);
     assert(Comm::IsConnOpen(conn));
-    comm_remove_close_handler(conn->fd, fwdServerClosedWrapper, this);
+    comm_remove_close_handler(conn->fd, closeHandler);
+    closeHandler = NULL;
     serverConn = NULL;
 }
 
@@ -884,7 +890,7 @@ FwdState::connectDone(const Comm::Connec
 
     debugs(17, 3, HERE << serverConnection() << ": '" << entry->url() << "'" );
 
-    comm_add_close_handler(serverConnection()->fd, fwdServerClosedWrapper, this);
+    closeHandler = comm_add_close_handler(serverConnection()->fd, fwdServerClosedWrapper, this);
 
     if (serverConnection()->getPeer())
         peerConnectSucceded(serverConnection()->getPeer());
@@ -988,7 +994,7 @@ FwdState::connectStart()
             request->hier.note(serverConn, pinned_connection->pinning.host);
             if (pinned_connection->pinnedAuth())
                 request->flags.auth = 1;
-            comm_add_close_handler(serverConn->fd, fwdServerClosedWrapper, this);
+            closeHandler = comm_add_close_handler(serverConn->fd, fwdServerClosedWrapper, this);
             // the server may close the pinned connection before this request
             pconnRace = racePossible;
             dispatch();
@@ -1024,7 +1030,7 @@ FwdState::connectStart()
         debugs(17, 3, HERE << "reusing pconn " << serverConnection());
         ++n_tries;
 
-        comm_add_close_handler(serverConnection()->fd, fwdServerClosedWrapper, this);
+        closeHandler = comm_add_close_handler(serverConnection()->fd, fwdServerClosedWrapper, this);
 
         /* Update server side TOS and Netfilter mark on the connection. */
         if (Ip::Qos::TheConfig.isAclTosActive()) {
Index: squid-3.3.13/src/Server.h
===================================================================
--- squid-3.3.13.orig/src/Server.h
+++ squid-3.3.13/src/Server.h
@@ -125,7 +125,9 @@ protected:
     virtual void sentRequestBody(const CommIoCbParams &io) = 0;
     virtual void doneSendingRequestBody() = 0;
 
-    virtual void closeServer() = 0;            /**< end communication with the server */
+    /// Use this to end communication with the server. The call cancels our
+    /// closure handler and tells FwdState to forget about the connection.
+    virtual void closeServer() = 0;
     virtual bool doneWithServer() const = 0;   /**< did we end communication? */
 
     /// Entry-dependent callbacks use this check to quit if the entry went bad
Index: squid-3.3.13/src/comm.cc
===================================================================
--- squid-3.3.13.orig/src/comm.cc
+++ squid-3.3.13/src/comm.cc
@@ -1221,7 +1221,7 @@ comm_udp_sendto(int fd,
     return COMM_ERROR;
 }
 
-void
+AsyncCall::Pointer
 comm_add_close_handler(int fd, CLCB * handler, void *data)
 {
     debugs(5, 5, "comm_add_close_handler: FD " << fd << ", handler=" <<
@@ -1230,6 +1230,7 @@ comm_add_close_handler(int fd, CLCB * ha
     AsyncCall::Pointer call=commCbCall(5,4, "SomeCloseHandler",
                                        CommCloseCbPtrFun(handler, data));
     comm_add_close_handler(fd, call);
+    return call;
 }
 
 void
Index: squid-3.3.13/src/comm.h
===================================================================
--- squid-3.3.13.orig/src/comm.h
+++ squid-3.3.13/src/comm.h
@@ -75,7 +75,7 @@ void commCloseAllSockets(void);
 void checkTimeouts(void);
 
 //typedef void IOACB(int fd, int nfd, Comm::ConnectionPointer details, comm_err_t flag, int xerrno, void *data);
-void comm_add_close_handler(int fd, CLCB *, void *);
+AsyncCall::Pointer comm_add_close_handler(int fd, CLCB *, void *);
 void comm_add_close_handler(int fd, AsyncCall::Pointer &);
 void comm_remove_close_handler(int fd, CLCB *, void *);
 void comm_remove_close_handler(int fd, AsyncCall::Pointer &);
Index: squid-3.3.13/src/http.cc
===================================================================
--- squid-3.3.13.orig/src/http.cc
+++ squid-3.3.13/src/http.cc
@@ -199,7 +199,8 @@ HttpStateData::httpTimeout(const CommTim
         fwd->fail(new ErrorState(ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT, fwd->request));
     }
 
-    serverConnection->close();
+    closeServer();
+    mustStop("HttpStateData::httpTimeout");
 }
 
 static void
@@ -1174,7 +1175,8 @@ HttpStateData::readReply(const CommIoCbP
             err->xerrno = io.xerrno;
             fwd->fail(err);
             flags.do_next_read = false;
-            serverConnection->close();
+            closeServer();
+            mustStop("HttpStateData::readReply");
         }
 
         return;
@@ -1327,7 +1329,8 @@ HttpStateData::continueAfterParsingHeade
     entry->reset();
     fwd->fail(new ErrorState(error, HTTP_BAD_GATEWAY, fwd->request));
     flags.do_next_read = false;
-    serverConnection->close();
+    closeServer();
+    mustStop("HttpStateData::continueAfterParsingHeader");
     return false; // quit on error
 }
 
@@ -1552,7 +1555,8 @@ HttpStateData::wroteLast(const CommIoCbP
         ErrorState *err = new ErrorState(ERR_WRITE_ERROR, HTTP_BAD_GATEWAY, fwd->request);
         err->xerrno = io.xerrno;
         fwd->fail(err);
-        serverConnection->close();
+        closeServer();
+        mustStop("HttpStateData::wroteLast");
         return;
     }
 
@@ -1580,7 +1584,6 @@ HttpStateData::sendComplete()
     request->hier.peer_http_request_sent = current_time;
 }
 
-// Close the HTTP server connection. Used by serverComplete().
 void
 HttpStateData::closeServer()
 {
@@ -2377,7 +2380,8 @@ HttpStateData::handleMoreRequestBodyAvai
             debugs(11, DBG_IMPORTANT, "http handleMoreRequestBodyAvailable: Likely proxy abuse detected '" << request->client_addr << "' -> '" << entry->url() << "'" );
 
             if (virginReply()->sline.status == HTTP_INVALID_HEADER) {
-                serverConnection->close();
+                closeServer();
+                mustStop("HttpStateData::handleMoreRequestBodyAvailable");
                 return;
             }
         }
