]> granicus.if.org Git - apache/commitdiff
* Correctly signal broken backend connections up the chain also for the ajp
authorRuediger Pluem <rpluem@apache.org>
Mon, 2 Jan 2006 16:39:22 +0000 (16:39 +0000)
committerRuediger Pluem <rpluem@apache.org>
Mon, 2 Jan 2006 16:39:22 +0000 (16:39 +0000)
  backend (see also r357461). Furthermore move common code in mod_proxy_http.c
  and mod_proxy_ajp.c into a new function (ap_proxy_backend_broke) in
  proxy_util.c.

  modules/proxy/mod_proxy_ajp.c : Signal broken backend connection for ajp backend
  modules/proxy/proxy_util.c    : Add ap_proxy_backend_broke
  modules/proxy/mod_proxy_http.c: - Use ap_proxy_backend_broke
                                  - Return DONE also if backend broke
  modules/proxy/mod_proxy.h     : Add declaration of ap_proxy_backend_broke

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@365374 13f79535-47bb-0310-9956-ffa450edef68

modules/proxy/mod_proxy.h
modules/proxy/mod_proxy_ajp.c
modules/proxy/mod_proxy_http.c
modules/proxy/proxy_util.c

index 63ed1afe2cfcf0435169720146ac70d6d96f483d..7bc092eac0480660200b36ccf438944db8aa36ea 100644 (file)
@@ -669,6 +669,15 @@ PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
 PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function,
                                               proxy_conn_rec *conn,
                                               conn_rec *c, server_rec *s);
+/**
+ * Signal the upstream chain that the connection to the backend broke in the
+ * middle of the response. This is done by sending an error bucket with
+ * status HTTP_BAD_GATEWAY and an EOS bucket up the filter chain.
+ * @param r       current request record of client request
+ * @param brigade The brigade that is sent through the output filter chain
+ */
+PROXY_DECLARE(void) ap_proxy_backend_broke(request_rec *r,
+                                           apr_bucket_brigade *brigade);
 
 /* Scoreboard */
 #if MODULE_MAGIC_NUMBER_MAJOR > 20020903
index 22e7cefcd7d030dba8bd4d5567d3cfcaafd6912c..abfaa0d2d81fe5c20bec64853c37fce28d7dbf1d 100644 (file)
@@ -138,6 +138,8 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r,
     int havebody = 1;
     int isok = 1;
     apr_off_t bb_len;
+    int data_sent = 0;
+    int rv = 0;
 #ifdef FLUSHING_BANDAID
     apr_int32_t conn_poll_fd;
     apr_pollfd_t *conn_poll;
@@ -348,6 +350,7 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r,
                                       "proxy: error processing body");
                         isok = 0;
                     }
+                    data_sent = 1;
                     apr_brigade_cleanup(output_brigade);
                 }
                 else {
@@ -363,6 +366,7 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r,
                                   "proxy: error processing body");
                     isok = 0;
                 }
+                data_sent = 1;
                 break;
             default:
                 isok = 0;
@@ -400,7 +404,11 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r,
     }
     apr_brigade_destroy(input_brigade);
 
-    apr_brigade_destroy(output_brigade);
+    /*
+     * Clear output_brigade to remove possible buckets that remained there
+     * after an error.
+     */
+    apr_brigade_cleanup(output_brigade);
 
     if (status != APR_SUCCESS) {
         /* We had a failure: Close connection to backend */
@@ -409,9 +417,37 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r,
                      "proxy: send body failed to %pI (%s)",
                      conn->worker->cp->addr,
                      conn->worker->hostname);
-        return HTTP_SERVICE_UNAVAILABLE;
+        /*
+         * If we already send data, signal a broken backend connection
+         * upwards in the chain.
+         */
+        if (data_sent) {
+            ap_proxy_backend_broke(r, output_brigade);
+            /* Return DONE to avoid error messages being added to the stream */
+            rv = DONE;
+        } else
+            rv = HTTP_SERVICE_UNAVAILABLE;
+    }
+
+    /*
+     * Ensure that we sent an EOS bucket thru the filter chain, if we already
+     * have sent some data. Maybe ap_proxy_backend_broke was called and added
+     * one to the brigade already. So we should not do this in this case.
+     */
+    if (data_sent && !r->eos_sent && APR_BRIGADE_EMPTY(output_brigade)) {
+        e = apr_bucket_eos_create(r->connection->bucket_alloc);
+        APR_BRIGADE_INSERT_TAIL(output_brigade, e);
     }
 
+    /* If we have added something to the brigade above, sent it */
+    if (!APR_BRIGADE_EMPTY(output_brigade))
+        ap_pass_brigade(r->output_filters, output_brigade);
+
+    apr_brigade_destroy(output_brigade);
+
+    if (rv)
+        return rv;
+
     /* Nice we have answer to send to the client */
     if (result == CMD_AJP13_END_RESPONSE && isok) {
         ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
index 31b892cbd59e53a1bf677f8ca462135dcf21e07b..b19ab5e9966906585b3ecdcd4e8076ef268b89d0 100644 (file)
@@ -1199,6 +1199,7 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
                            * are being read. */
     int pread_len = 0;
     apr_table_t *save_table;
+    int backend_broke = 0;
 
     bb = apr_brigade_create(p, c->bucket_alloc);
 
@@ -1486,13 +1487,9 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
                          */
                         ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c,
                                       "proxy: error reading response");
-                        r->no_cache = 1;
-                        e = ap_bucket_error_create(HTTP_BAD_GATEWAY,  NULL,
-                                                   c->pool, c->bucket_alloc);
-                        APR_BRIGADE_INSERT_TAIL(bb, e);
-                        e = apr_bucket_eos_create(c->bucket_alloc);
-                        APR_BRIGADE_INSERT_TAIL(bb, e);
+                        ap_proxy_backend_broke(r, bb);
                         ap_pass_brigade(r->output_filters, bb);
+                        backend_broke = 1;
                         backend->close = 1;
                         break;
                     }
@@ -1560,7 +1557,7 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
     } while (interim_response);
 
     /* If our connection with the client is to be aborted, return DONE. */
-    if (c->aborted) {
+    if (c->aborted || backend_broke) {
         return DONE;
     }
 
index 410f501711cea7b4795053974ebf101d5da409d8..da2cc1ffe99a25fe8d863458f52a6019c6b0c78b 100644 (file)
@@ -2129,3 +2129,17 @@ int ap_proxy_lb_workers(void)
     lb_workers_limit = proxy_lb_workers + PROXY_DYNAMIC_BALANCER_LIMIT;
     return lb_workers_limit;
 }
+
+PROXY_DECLARE(void) ap_proxy_backend_broke(request_rec *r,
+                                           apr_bucket_brigade *brigade)
+{
+    apr_bucket *e;
+    conn_rec *c = r->connection;
+
+    r->no_cache = 1;
+    e = ap_bucket_error_create(HTTP_BAD_GATEWAY, NULL, c->pool,
+                               c->bucket_alloc);
+    APR_BRIGADE_INSERT_TAIL(brigade, e);
+    e = apr_bucket_eos_create(c->bucket_alloc);
+    APR_BRIGADE_INSERT_TAIL(brigade, e);
+}