From: Ruediger Pluem Date: Mon, 2 Jan 2006 16:39:22 +0000 (+0000) Subject: * Correctly signal broken backend connections up the chain also for the ajp X-Git-Tag: 2.3.0~2637 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=30d205d8a9072c7d3f46bea3b374d386afb607b7;p=apache * Correctly signal broken backend connections up the chain also for the ajp 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 --- diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h index 63ed1afe2c..7bc092eac0 100644 --- a/modules/proxy/mod_proxy.h +++ b/modules/proxy/mod_proxy.h @@ -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 diff --git a/modules/proxy/mod_proxy_ajp.c b/modules/proxy/mod_proxy_ajp.c index 22e7cefcd7..abfaa0d2d8 100644 --- a/modules/proxy/mod_proxy_ajp.c +++ b/modules/proxy/mod_proxy_ajp.c @@ -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, diff --git a/modules/proxy/mod_proxy_http.c b/modules/proxy/mod_proxy_http.c index 31b892cbd5..b19ab5e996 100644 --- a/modules/proxy/mod_proxy_http.c +++ b/modules/proxy/mod_proxy_http.c @@ -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; } diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c index 410f501711..da2cc1ffe9 100644 --- a/modules/proxy/proxy_util.c +++ b/modules/proxy/proxy_util.c @@ -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); +}