From 9d58cd69902b69f2ebea62128a9319a5626abd32 Mon Sep 17 00:00:00 2001 From: Graham Leggett Date: Sat, 23 Oct 2010 19:26:44 +0000 Subject: [PATCH] mod_proxy: Release the backend connection as soon as EOS is detected, so the backend isn't forced to wait for the client to eventually acknowledge the data. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1026665 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 4 ++++ modules/proxy/mod_proxy.h | 1 + modules/proxy/mod_proxy_http.c | 18 ++++++++++++++++++ modules/proxy/proxy_util.c | 11 +++++++---- 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index c61a187804..9e925d38ed 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,10 @@ Changes with Apache 2.3.9 Fix a denial of service attack against mod_reqtimeout. [Stefan Fritsch] + *) mod_proxy: Release the backend connection as soon as EOS is detected, + so the backend isn't forced to wait for the client to eventually + acknowledge the data. [Graham Leggett] + *) mod_proxy: Optimise ProxyPass within a Location so that it is stored per-directory, and chosen during the location walk. Make ProxyPass work correctly from within a LocationMatch. [Graham Leggett] diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h index 021ccec8f9..d02a252532 100644 --- a/modules/proxy/mod_proxy.h +++ b/modules/proxy/mod_proxy.h @@ -233,6 +233,7 @@ typedef struct { #if APR_HAS_THREADS char inreslist; /* connection in apr_reslist? */ #endif + int cleaned:1; /* connection cleaned? */ } proxy_conn_rec; typedef struct { diff --git a/modules/proxy/mod_proxy_http.c b/modules/proxy/mod_proxy_http.c index e636b73074..9454758d71 100644 --- a/modules/proxy/mod_proxy_http.c +++ b/modules/proxy/mod_proxy_http.c @@ -1905,8 +1905,18 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r, /* found the last brigade? */ if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) { + /* signal that we must leave */ finish = TRUE; + + /* 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 */ @@ -1930,6 +1940,14 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r, ap_log_error(APLOG_MARK, APLOG_TRACE2, 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); diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c index d5f1ae706f..320ec5a968 100644 --- a/modules/proxy/proxy_util.c +++ b/modules/proxy/proxy_util.c @@ -2104,10 +2104,13 @@ PROXY_DECLARE(int) ap_proxy_release_connection(const char *proxy_function, 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; } -- 2.40.0