From fbf179056aec2c4d1aa9cc1cd346c7b7f2f24e11 Mon Sep 17 00:00:00 2001 From: Jim Jagielski Date: Tue, 31 Mar 2015 12:53:00 +0000 Subject: [PATCH] Merge r1657636, r1657638, r1669130 from trunk: mod_proxy_connect/wstunnel: If both client and backend sides get readable at the same time, don't lose errors occuring while forwarding on the first side when none occurs next on the other side, and abort. CHANGES: Follow up to r1657636, clarify message. mod_proxy_{connect,wstunnel}: follow up to r1657636. Since rv is not used as an apr_status_t in the loop (it's logging is done by proxy_{connect,wstunnel}_transfer() when necessary/relevent), use a boolean instead to avoid the ugly ORs between APR error codes. Submitted by: ylavic Reviewed/backported by: jim git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1670324 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 4 ++++ modules/proxy/mod_proxy_connect.c | 28 +++++++++++----------- modules/proxy/mod_proxy_wstunnel.c | 38 +++++++++++++++--------------- 3 files changed, 37 insertions(+), 33 deletions(-) diff --git a/CHANGES b/CHANGES index dacac4c549..e2adc759e5 100644 --- a/CHANGES +++ b/CHANGES @@ -30,6 +30,10 @@ Changes with Apache 2.4.13 a ProxyRemote forward-proxy. PR 55892. [Hendrik Harms , William Rowe, Yann Ylavic] + *) mod_proxy_connect/wstunnel: If both client and backend sides get readable + at the same time, don't lose errors occuring while forwarding on the first + side when none occurs next on the other side, and abort. [Yann Ylavic] + *) mod_rewrite: Improve relative substitutions in per-directory/htaccess context for directories found by mod_userdir and mod_alias. These no longer require RewriteBase to be specified. [Eric Covener] diff --git a/modules/proxy/mod_proxy_connect.c b/modules/proxy/mod_proxy_connect.c index 55079148f0..e958b4476c 100644 --- a/modules/proxy/mod_proxy_connect.c +++ b/modules/proxy/mod_proxy_connect.c @@ -203,6 +203,7 @@ static int proxy_connect_handler(request_rec *r, proxy_worker *worker, apr_socket_t *sock; conn_rec *c = r->connection; conn_rec *backconn; + int done = 0; apr_bucket_brigade *bb = apr_brigade_create(p, c->bucket_alloc); apr_status_t rv; @@ -413,9 +414,9 @@ static int proxy_connect_handler(request_rec *r, proxy_worker *worker, r->proto_input_filters = c->input_filters; /* r->sent_bodyct = 1;*/ - while (1) { /* Infinite loop until error (one side closes the connection) */ - if ((rv = apr_pollset_poll(pollset, -1, &pollcnt, &signalled)) - != APR_SUCCESS) { + do { /* Loop until done (one side closes the connection, or an error) */ + rv = apr_pollset_poll(pollset, -1, &pollcnt, &signalled); + if (rv != APR_SUCCESS) { if (APR_STATUS_IS_EINTR(rv)) { continue; } @@ -438,13 +439,14 @@ static int proxy_connect_handler(request_rec *r, proxy_worker *worker, ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01025) "sock was readable"); #endif - rv = proxy_connect_transfer(r, backconn, c, bb, "sock"); + done |= proxy_connect_transfer(r, backconn, c, bb, + "sock") != APR_SUCCESS; } else if (pollevent & APR_POLLERR) { - rv = APR_EPIPE; - backconn->aborted = 1; ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, APLOGNO(01026) "err on backconn"); + backconn->aborted = 1; + done = 1; } } else if (cur->desc.s == client_socket) { @@ -454,26 +456,24 @@ static int proxy_connect_handler(request_rec *r, proxy_worker *worker, ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01027) "client was readable"); #endif - rv = proxy_connect_transfer(r, c, backconn, bb, "client"); + done |= proxy_connect_transfer(r, c, backconn, bb, + "client") != APR_SUCCESS; } else if (pollevent & APR_POLLERR) { - rv = APR_EPIPE; - c->aborted = 1; ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, APLOGNO(02827) "err on client"); + c->aborted = 1; + done = 1; } } else { - rv = APR_EBADF; ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(01028) "unknown socket in pollset"); + done = 1; } } - if (rv != APR_SUCCESS) { - break; - } - } + } while (!done); ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, "finished with poll() - cleaning up"); diff --git a/modules/proxy/mod_proxy_wstunnel.c b/modules/proxy/mod_proxy_wstunnel.c index 1eb6ac89ef..1dd7e658e9 100644 --- a/modules/proxy/mod_proxy_wstunnel.c +++ b/modules/proxy/mod_proxy_wstunnel.c @@ -90,10 +90,10 @@ static int proxy_wstunnel_canon(request_rec *r, char *url) } -static int proxy_wstunnel_transfer(request_rec *r, conn_rec *c_i, conn_rec *c_o, +static apr_status_t proxy_wstunnel_transfer(request_rec *r, conn_rec *c_i, conn_rec *c_o, apr_bucket_brigade *bb, char *name) { - int rv; + apr_status_t rv; #ifdef DEBUGGING apr_off_t len; #endif @@ -137,7 +137,7 @@ static int proxy_wstunnel_transfer(request_rec *r, conn_rec *c_i, conn_rec *c_o, if (APR_STATUS_IS_EAGAIN(rv)) { rv = APR_SUCCESS; } - + return rv; } @@ -167,6 +167,7 @@ static int proxy_wstunnel_request(apr_pool_t *p, request_rec *r, char *old_te_val = NULL; apr_bucket_brigade *bb = apr_brigade_create(p, c->bucket_alloc); apr_socket_t *client_socket = ap_get_conn_socket(c); + int done = 0; header_brigade = apr_brigade_create(p, backconn->bucket_alloc); @@ -224,9 +225,9 @@ static int proxy_wstunnel_request(apr_pool_t *p, request_rec *r, * nothing else is attempted on the connection after returning. */ c->keepalive = AP_CONN_CLOSE; - while (1) { /* Infinite loop until error (one side closes the connection) */ - if ((rv = apr_pollset_poll(pollset, -1, &pollcnt, &signalled)) - != APR_SUCCESS) { + do { /* Loop until done (one side closes the connection, or an error) */ + rv = apr_pollset_poll(pollset, -1, &pollcnt, &signalled); + if (rv != APR_SUCCESS) { if (APR_STATUS_IS_EINTR(rv)) { continue; } @@ -244,18 +245,19 @@ static int proxy_wstunnel_request(apr_pool_t *p, request_rec *r, if (pollevent & (APR_POLLIN | APR_POLLHUP)) { ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, APLOGNO(02446) "sock was readable"); - rv = proxy_wstunnel_transfer(r, backconn, c, bb, "sock"); + done |= proxy_wstunnel_transfer(r, backconn, c, bb, + "sock") != APR_SUCCESS; } else if (pollevent & APR_POLLERR) { - rv = APR_EPIPE; - backconn->aborted = 1; ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, APLOGNO(02447) "error on backconn"); + backconn->aborted = 1; + done = 1; } else { - rv = APR_EGENERAL; ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, APLOGNO(02605) "unknown event on backconn %d", pollevent); + done = 1; } } else if (cur->desc.s == client_socket) { @@ -263,31 +265,29 @@ static int proxy_wstunnel_request(apr_pool_t *p, request_rec *r, if (pollevent & (APR_POLLIN | APR_POLLHUP)) { ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, APLOGNO(02448) "client was readable"); - rv = proxy_wstunnel_transfer(r, c, backconn, bb, "client"); + done |= proxy_wstunnel_transfer(r, c, backconn, bb, + "client") != APR_SUCCESS; } else if (pollevent & APR_POLLERR) { - rv = APR_EPIPE; - c->aborted = 1; ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, APLOGNO(02607) "error on client conn"); + c->aborted = 1; + done = 1; } else { - rv = APR_EGENERAL; ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, APLOGNO(02606) "unknown event on client conn %d", pollevent); + done = 1; } } else { - rv = APR_EBADF; ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(02449) "unknown socket in pollset"); + done = 1; } } - if (rv != APR_SUCCESS) { - break; - } - } + } while (!done); ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, "finished with poll() - cleaning up"); -- 2.40.0