PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
[ start all new proposals below, under PATCHES PROPOSED. ]
-
- *) mod_proxy: Fix a race condition that caused a failed worker to be retried
- before the retry period is over
- Trunk version of patch:
- http://svn.apache.org/r1664709
- http://svn.apache.org/r1697323
- Backport version for 2.4.x of patch:
- Trunk version of patch works modulo CHANGES
- +1: rpluem, ylavic, jim
- niq: 1. the if(worker->s->retries) {} and comment at line 2917
- don't seem to make any sense.
- rpluem: This is just taken over from existing code. It is just indented
- differently hence part of the path I think it should be marked
- as TODO section. But this should be subject to another
- patch.
- 2. Re: error handline line 2930 - can PROXY_WORKER_IS_USABLE
- not be tested BEFORE opening connection?
- rpluem: We could, but we can catch more race cases with the current code
- as it also catches the case where a connection establishment
- took long and the worker went into error meanwhile.
-
+
PATCHES PROPOSED TO BACKPORT FROM TRUNK:
[ New proposals should be added at the end of the list ]
connected = 1;
}
- /*
- * Put the entire worker to error state if
- * the PROXY_WORKER_IGNORE_ERRORS flag is not set.
- * Altrough some connections may be alive
- * no further connections to the worker could be made
- */
- if (!connected && PROXY_WORKER_IS_USABLE(worker) &&
- !(worker->s->status & PROXY_WORKER_IGNORE_ERRORS)) {
- worker->s->error_time = apr_time_now();
- worker->s->status |= PROXY_WORKER_IN_ERROR;
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00959)
- "ap_proxy_connect_backend disabling worker for (%s) for %"
- APR_TIME_T_FMT "s",
- worker->s->hostname, apr_time_sec(worker->s->retry));
+ if (PROXY_WORKER_IS_USABLE(worker)) {
+ /*
+ * Put the entire worker to error state if
+ * the PROXY_WORKER_IGNORE_ERRORS flag is not set.
+ * Although some connections may be alive
+ * no further connections to the worker could be made
+ */
+ if (!connected) {
+ if (!(worker->s->status & PROXY_WORKER_IGNORE_ERRORS)) {
+ worker->s->error_time = apr_time_now();
+ worker->s->status |= PROXY_WORKER_IN_ERROR;
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00959)
+ "ap_proxy_connect_backend disabling worker for (%s) for %"
+ APR_TIME_T_FMT "s",
+ worker->s->hostname, apr_time_sec(worker->s->retry));
+ }
+ }
+ else {
+ if (worker->s->retries) {
+ /*
+ * A worker came back. So here is where we need to
+ * either reset all params to initial conditions or
+ * apply some sort of aging
+ */
+ }
+ worker->s->error_time = 0;
+ worker->s->retries = 0;
+ }
+ return connected ? OK : DECLINED;
}
else {
- if (worker->s->retries) {
- /*
- * A worker came back. So here is where we need to
- * either reset all params to initial conditions or
- * apply some sort of aging
- */
+ /*
+ * The worker is in error likely done by a different thread / process
+ * e.g. for a timeout or bad status. We should respect this and should
+ * not continue with a connection via this worker even if we got one.
+ */
+ if (connected) {
+ socket_cleanup(conn);
}
- worker->s->error_time = 0;
- worker->s->retries = 0;
+ return DECLINED;
}
- return connected ? OK : DECLINED;
}
static apr_status_t connection_shutdown(void *theconn)