summaryrefslogtreecommitdiffstats
path: root/modules/proxy/proxy_util.c
diff options
context:
space:
mode:
authorEric Covener <covener@apache.org>2019-08-26 16:19:31 +0200
committerEric Covener <covener@apache.org>2019-08-26 16:19:31 +0200
commit1dfc69425958ffbc3fb5c384348d571c4abca6bb (patch)
treeca4ca83b9987d1c7649a6e782af537275ba3ca9d /modules/proxy/proxy_util.c
parentremove APR_HAS_THREADS check (diff)
downloadapache2-1dfc69425958ffbc3fb5c384348d571c4abca6bb.tar.xz
apache2-1dfc69425958ffbc3fb5c384348d571c4abca6bb.zip
PR63503: fix pool concurrency problems in mod_proxy
reslist and resolver related calls could concurrently access the same pool. Submitted By: Don Poitras <Don.Poitras sas.com> Committed By: covener git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1865938 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'modules/proxy/proxy_util.c')
-rw-r--r--modules/proxy/proxy_util.c34
1 files changed, 29 insertions, 5 deletions
diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c
index 1b528b9b1c..1c2c0bade6 100644
--- a/modules/proxy/proxy_util.c
+++ b/modules/proxy/proxy_util.c
@@ -2055,22 +2055,34 @@ PROXY_DECLARE(apr_status_t) ap_proxy_initialize_worker(proxy_worker *worker, ser
if (worker->tmutex == NULL) {
rv = apr_thread_mutex_create(&(worker->tmutex), APR_THREAD_MUTEX_DEFAULT, p);
if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00928)
+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00928)
"can not create worker thread mutex");
apr_global_mutex_unlock(proxy_mutex);
return rv;
}
}
+ if ((rv = PROXY_THREAD_LOCK(worker)) != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO() "lock");
+ apr_global_mutex_unlock(proxy_mutex);
+ return rv;
+ }
#endif
if (worker->cp == NULL)
init_conn_pool(p, worker);
if (worker->cp == NULL) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00929)
"can not create connection pool");
+ if ((rv = PROXY_THREAD_UNLOCK(worker)) != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO() "unlock");
+ }
apr_global_mutex_unlock(proxy_mutex);
return APR_EGENERAL;
}
+ if ((rv = PROXY_THREAD_UNLOCK(worker)) != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO() "unlock");
+ }
+
if (worker->s->hmax) {
rv = apr_reslist_create(&(worker->cp->res),
worker->s->min, worker->s->smax,
@@ -2098,13 +2110,16 @@ PROXY_DECLARE(apr_status_t) ap_proxy_initialize_worker(proxy_worker *worker, ser
rv = connection_constructor(&conn, worker, worker->cp->pool);
worker->cp->conn = conn;
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00931)
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s, APLOGNO(00931)
"initialized single connection worker in child %" APR_PID_T_FMT " for (%s)",
getpid(), worker->s->hostname_ex);
}
+ if ((rv = PROXY_THREAD_UNLOCK(worker)) != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO() "unlock");
+ }
apr_global_mutex_unlock(proxy_mutex);
- }
+ } /* init worker */
if (rv == APR_SUCCESS) {
worker->s->status |= (PROXY_WORKER_INITIALIZED);
worker->local_status |= (PROXY_WORKER_INITIALIZED);
@@ -2348,6 +2363,7 @@ PROXY_DECLARE(int) ap_proxy_acquire_connection(const char *proxy_function,
server_rec *s)
{
apr_status_t rv;
+ apr_status_t err;
if (!PROXY_WORKER_IS_USABLE(worker)) {
/* Retry the worker */
@@ -2362,18 +2378,26 @@ PROXY_DECLARE(int) ap_proxy_acquire_connection(const char *proxy_function,
}
if (worker->s->hmax && worker->cp->res) {
+ if ((err = PROXY_THREAD_LOCK(worker)) != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, err, s, APLOGNO() "lock");
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
rv = apr_reslist_acquire(worker->cp->res, (void **)conn);
+ if ((err = PROXY_THREAD_UNLOCK(worker)) != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, err, s, APLOGNO() "unlock");
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
}
else {
/* create the new connection if the previous was destroyed */
if (!worker->cp->conn) {
- connection_constructor((void **)conn, worker, worker->cp->pool);
+ rv = connection_constructor((void **)conn, worker, worker->cp->pool);
}
else {
*conn = worker->cp->conn;
worker->cp->conn = NULL;
+ rv = APR_SUCCESS;
}
- rv = APR_SUCCESS;
}
if (rv != APR_SUCCESS) {