From: Yann Ylavic Date: Mon, 27 Jun 2016 08:00:30 +0000 (+0000) Subject: mod_proxy: don't reuse backend connections with data available before the X-Git-Tag: 2.5.0-alpha~1470 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d2e75e1d51c250d8d17016943a1e01a015b70c4c;p=apache mod_proxy: don't reuse backend connections with data available before the request is sent. PR 57832. [Reverted by r1750376] git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1750301 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h index 467984dfa8..268ebc37d5 100644 --- a/modules/proxy/mod_proxy.h +++ b/modules/proxy/mod_proxy.h @@ -271,6 +271,7 @@ typedef struct { unsigned int inreslist:1; /* connection in apr_reslist? */ const char *uds_path; /* Unix domain socket path */ const char *ssl_hostname;/* Hostname (SNI) in use by SSL connection */ + apr_bucket_brigade *tmp_bb; } proxy_conn_rec; typedef struct { diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c index 6fee211e5b..908c1d6e72 100644 --- a/modules/proxy/proxy_util.c +++ b/modules/proxy/proxy_util.c @@ -2487,7 +2487,7 @@ ap_proxy_determine_connection(apr_pool_t *p, request_rec *r, #endif #if USE_ALTERNATE_IS_CONNECTED && defined(APR_MSG_PEEK) -PROXY_DECLARE(int) ap_proxy_is_socket_connected(apr_socket_t *socket) +static int get_socket_connected(apr_socket_t *socket) { apr_pollfd_t pfds[1]; apr_status_t status; @@ -2514,7 +2514,7 @@ PROXY_DECLARE(int) ap_proxy_is_socket_connected(apr_socket_t *socket) status = apr_socket_recvfrom(&unused, socket, APR_MSG_PEEK, &buf[0], &len); if (status == APR_SUCCESS && len) - return 1; + return 2; else return 0; } @@ -2525,7 +2525,7 @@ PROXY_DECLARE(int) ap_proxy_is_socket_connected(apr_socket_t *socket) } #else -PROXY_DECLARE(int) ap_proxy_is_socket_connected(apr_socket_t *socket) +static int is_socket_connnected(apr_socket_t *socket) { apr_size_t buffer_len = 1; @@ -2544,12 +2544,19 @@ PROXY_DECLARE(int) ap_proxy_is_socket_connected(apr_socket_t *socket) || APR_STATUS_IS_ECONNRESET(socket_status)) { return 0; } + else if (status == APR_SUCCESS && buffer_len) { + return 2; + } else { return 1; } } #endif /* USE_ALTERNATE_IS_CONNECTED */ +PROXY_DECLARE(int) ap_proxy_is_socket_connected(apr_socket_t *socket) +{ + return get_socket_connected(socket) != 0; +} /* * Send a HTTP CONNECT request to a forward proxy. @@ -2716,7 +2723,35 @@ PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function, (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); if (conn->sock) { - if (!(connected = ap_proxy_is_socket_connected(conn->sock))) { + conn_rec *c = conn->connection; + if (!c) { + connected = get_socket_connected(conn->sock); + } + else { + if (conn->tmp_bb == NULL) { + conn->tmp_bb = apr_brigade_create(c->pool, c->bucket_alloc); + } + rv = ap_get_brigade(c->input_filters, conn->tmp_bb, + AP_MODE_SPECULATIVE, APR_NONBLOCK_READ, 1); + if (rv == APR_SUCCESS) { + apr_off_t len = 0; + apr_brigade_length(conn->tmp_bb, 0, &len); + if (len) { + connected = 2; + } + else { + connected = 1; + } + } + else if (APR_STATUS_IS_EAGAIN(rv)) { + connected = 1; + } + else { + connected = 0; + } + apr_brigade_cleanup(conn->tmp_bb); + } + if (connected != 1) { /* This clears conn->scpool (and associated data), so backup and * restore any ssl_hostname for this connection set earlier by * ap_proxy_determine_connection(). @@ -2728,9 +2763,17 @@ PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function, } socket_cleanup(conn); - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00951) - "%s: backend socket is disconnected.", - proxy_function); + if (!connected) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00951) + "%s: backend socket is disconnected.", + proxy_function); + } + else { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO() + "%s: reusable backend connection is not empty: " + "forcibly closed", proxy_function); + connected = 0; + } if (ssl_hostname[0]) { conn->ssl_hostname = apr_pstrdup(conn->scpool, ssl_hostname);