]> granicus.if.org Git - apache/commitdiff
mod_proxy: Release the backend connection as soon as EOS is detected,
authorGraham Leggett <minfrin@apache.org>
Sat, 23 Oct 2010 19:26:44 +0000 (19:26 +0000)
committerGraham Leggett <minfrin@apache.org>
Sat, 23 Oct 2010 19:26:44 +0000 (19:26 +0000)
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
modules/proxy/mod_proxy.h
modules/proxy/mod_proxy_http.c
modules/proxy/proxy_util.c

diff --git a/CHANGES b/CHANGES
index c61a1878045343b7c188762bdb9091df83dc265f..9e925d38ed5e8177159bbbeb867f49b81bc56ce2 100644 (file)
--- 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]
index 021ccec8f9314f2ab2dcf546e0d8082ae680ae88..d02a2525329b8266d4edb0dcc2fb75aac6430883 100644 (file)
@@ -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 {
index e636b73074a85388a77ed21f8b3fc12d701780c5..9454758d71e0bc5878955bdbf0d819dcf486bdd6 100644 (file)
@@ -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);
index d5f1ae706f44f76186aee8baba94be9a327364d6..320ec5a9680e318bd51661fb9fdf3c881caca57a 100644 (file)
@@ -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;
 }