diff --git a/docs/log-message-tags/next-number b/docs/log-message-tags/next-number index 1db299c003..ea5f1c5174 100644 --- a/docs/log-message-tags/next-number +++ b/docs/log-message-tags/next-number @@ -1 +1 @@ -2460 +2461 diff --git a/docs/manual/mod/mod_proxy.xml b/docs/manual/mod/mod_proxy.xml index 1288423308..4de2cb28e9 100644 --- a/docs/manual/mod/mod_proxy.xml +++ b/docs/manual/mod/mod_proxy.xml @@ -1138,6 +1138,12 @@ ProxyPass /mirror/foo http://backend.example.com force the worker into error state when the backend returns any status code in the list. Worker recovery behaves the same as other worker errors. +
balancer-manager
application page.
diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c
index b5ff09bbc4..58cbfb8315 100644
--- a/modules/proxy/mod_proxy.c
+++ b/modules/proxy/mod_proxy.c
@@ -383,6 +383,14 @@ static const char *set_balancer_param(proxy_server_conf *conf,
}
}
+ else if (!strcasecmp(key, "failontimeout")) {
+ if (!strcasecmp(val, "on"))
+ balancer->failontimeout = 1;
+ else if (!strcasecmp(val, "off"))
+ balancer->failontimeout = 0;
+ else
+ return "failontimeout must be On|Off";
+ }
else if (!strcasecmp(key, "nonce")) {
if (!strcasecmp(val, "None")) {
*balancer->s->nonce = '\0';
diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h
index a6ab92cc76..43835b1b76 100644
--- a/modules/proxy/mod_proxy.h
+++ b/modules/proxy/mod_proxy.h
@@ -451,6 +451,7 @@ struct proxy_balancer {
proxy_server_conf *sconf;
void *context; /* general purpose storage */
proxy_balancer_shared *s; /* Shared data */
+ int failontimeout; /* Whether to mark a member in Err if IO timeout occurs */
};
struct proxy_balancer_method {
diff --git a/modules/proxy/mod_proxy_ajp.c b/modules/proxy/mod_proxy_ajp.c
index e796f73b5e..46cda6ed10 100644
--- a/modules/proxy/mod_proxy_ajp.c
+++ b/modules/proxy/mod_proxy_ajp.c
@@ -662,6 +662,7 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r,
* but doesn't affect the whole worker.
*/
if (APR_STATUS_IS_TIMEUP(status) && conn->worker->s->ping_timeout_set) {
+ apr_table_set(r->notes, "proxy_timedout", "1");
rv = HTTP_GATEWAY_TIME_OUT;
}
else {
diff --git a/modules/proxy/mod_proxy_balancer.c b/modules/proxy/mod_proxy_balancer.c
index cd9987e192..b1fd84eeb5 100644
--- a/modules/proxy/mod_proxy_balancer.c
+++ b/modules/proxy/mod_proxy_balancer.c
@@ -649,6 +649,17 @@ static int proxy_balancer_post_request(proxy_worker *worker,
}
}
+ if (balancer->failontimeout
+ && (apr_table_get(r->notes, "proxy_timedout")) != NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02460)
+ "%s: Forcing worker (%s) into error state "
+ "due to timeout and 'failonstatus' parameter being set",
+ balancer->s->name, worker->s->name);
+ worker->s->status |= PROXY_WORKER_IN_ERROR;
+ worker->s->error_time = apr_time_now();
+
+ }
+
if ((rv = PROXY_THREAD_UNLOCK(balancer)) != APR_SUCCESS) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01175)
"%s: Unlock failed for post_request", balancer->s->name);
diff --git a/modules/proxy/mod_proxy_http.c b/modules/proxy/mod_proxy_http.c
index 543afada51..0712b61d5f 100644
--- a/modules/proxy/mod_proxy_http.c
+++ b/modules/proxy/mod_proxy_http.c
@@ -1312,6 +1312,7 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
"error reading status line from remote "
"server %s:%d", backend->hostname, backend->port);
if (APR_STATUS_IS_TIMEUP(rc)) {
+ apr_table_set(r->notes, "proxy_timedout", "1");
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01103) "read timeout");
if (do_100_continue) {
return ap_proxyerror(r, HTTP_SERVICE_UNAVAILABLE, "Timeout on 100-Continue");