Index: modules/proxy/proxy_util.c =================================================================== --- modules/proxy/proxy_util.c (revision 1035508) +++ modules/proxy/proxy_util.c (working copy) @@ -2018,6 +2018,7 @@ #if APR_HAS_THREADS (*conn)->inreslist = 0; #endif + (*conn)->cleaned = 0; return OK; } @@ -2026,10 +2027,13 @@ proxy_conn_rec *conn, server_rec *s) { - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "proxy: %s: has released connection for (%s)", - proxy_function, conn->worker->hostname); - connection_cleanup(conn); + if (!conn->cleaned) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + "proxy: %s: has released connection for (%s)", + proxy_function, conn->worker->hostname); + connection_cleanup(conn); + conn->cleaned = 1; + } return OK; } Index: modules/proxy/mod_proxy_http.c =================================================================== --- modules/proxy/mod_proxy_http.c (revision 1035508) +++ modules/proxy/mod_proxy_http.c (working copy) @@ -1817,9 +1817,36 @@ ap_proxy_buckets_lifetime_transform(r, bb, pass_bb); /* found the last brigade? */ - if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) { + if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(pass_bb))) { + /* signal that we must leave */ finish = TRUE; + + /* the brigade may contain transient buckets that contain + * data that lives only as long as the backend connection. + * Force a setaside so these transient buckets become heap + * buckets that live as long as the request. + */ + for (e = APR_BRIGADE_FIRST(pass_bb); e + != APR_BRIGADE_SENTINEL(pass_bb); e + = APR_BUCKET_NEXT(e)) { + apr_bucket_setaside(e, r->pool); + } + + /* finally it is safe to clean up the brigade from the + * connection pool, as we have forced a setaside on all + * buckets. + */ + apr_brigade_cleanup(bb); + + /* make sure we release the backend connection as soon + * as we know we are done, so that the backend isn't + * left waiting for a slow client to eventually + * acknowledge the data. + */ + ap_proxy_release_connection(backend->worker->scheme, + backend, r->server); + } /* try send what we read */ @@ -1831,8 +1858,8 @@ } /* make sure we always clean up after ourselves */ + apr_brigade_cleanup(pass_bb); apr_brigade_cleanup(bb); - apr_brigade_cleanup(pass_bb); } while (!finish); } @@ -1843,6 +1870,14 @@ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "proxy: header only"); + /* make sure we release the backend connection as soon + * as we know we are done, so that the backend isn't + * left waiting for a slow client to eventually + * acknowledge the data. + */ + ap_proxy_release_connection(backend->worker->scheme, + backend, r->server); + /* Pass EOS bucket down the filter chain. */ e = apr_bucket_eos_create(c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bb, e); Index: modules/proxy/mod_proxy.h =================================================================== --- modules/proxy/mod_proxy.h (revision 1035508) +++ modules/proxy/mod_proxy.h (working copy) @@ -248,6 +248,7 @@ int need_flush;/* Flag to decide whether we need to flush the * filter chain or not */ void *forward; /* opaque forward proxy data */ + int cleaned:1; /* connection cleaned? */ } proxy_conn_rec; typedef struct {