1
0
mirror of https://github.com/apache/httpd.git synced 2025-08-08 15:02:10 +03:00

Fix pool lifetime issues when the proxy backend connection is terminated

early by forcing a setaside on transient buckets placed in the brigade
by mod_ssl. This has the effect of extending the lifetime of buckets until
the end of the request. This is a variation on the original fix for this
problem, which added transient buckets to be setaside later in the process.


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1035504 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Graham Leggett
2010-11-16 00:23:37 +00:00
parent ec5ecdba66
commit 38437740bb
4 changed files with 18 additions and 86 deletions

View File

@@ -284,12 +284,13 @@
* 20101106.1 (2.3.9-dev) Add ap_pool_cleanup_set_null() generic cleanup * 20101106.1 (2.3.9-dev) Add ap_pool_cleanup_set_null() generic cleanup
* 20101106.2 (2.3.9-dev) Add suexec_disabled_reason field to ap_unixd_config * 20101106.2 (2.3.9-dev) Add suexec_disabled_reason field to ap_unixd_config
* 20101113.0 (2.3.9-dev) Add source address to mod_proxy.h * 20101113.0 (2.3.9-dev) Add source address to mod_proxy.h
* 20101116.0 (2.3.9-dev) Remove ap_proxy_buckets_lifetime_transform()
*/ */
#define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */ #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
#ifndef MODULE_MAGIC_NUMBER_MAJOR #ifndef MODULE_MAGIC_NUMBER_MAJOR
#define MODULE_MAGIC_NUMBER_MAJOR 20101113 #define MODULE_MAGIC_NUMBER_MAJOR 20101116
#endif #endif
#define MODULE_MAGIC_NUMBER_MINOR 0 /* 0...n */ #define MODULE_MAGIC_NUMBER_MINOR 0 /* 0...n */

View File

@@ -778,28 +778,6 @@ PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function,
PROXY_DECLARE(void) ap_proxy_backend_broke(request_rec *r, PROXY_DECLARE(void) ap_proxy_backend_broke(request_rec *r,
apr_bucket_brigade *brigade); apr_bucket_brigade *brigade);
/**
* Transform buckets from one bucket allocator to another one by creating a
* transient bucket for each data bucket and let it use the data read from
* the old bucket. Metabuckets are transformed by just recreating them.
* Attention: Currently only the following bucket types are handled:
*
* All data buckets
* FLUSH
* EOS
*
* If an other bucket type is found its type is logged as a debug message
* and APR_EGENERAL is returned.
* @param r current request record of client request. Only used for logging
* purposes
* @param from the brigade that contains the buckets to transform
* @param to the brigade that will receive the transformed buckets
* @return APR_SUCCESS if all buckets could be transformed APR_EGENERAL
* otherwise
*/
PROXY_DECLARE(apr_status_t)
ap_proxy_buckets_lifetime_transform(request_rec *r, apr_bucket_brigade *from,
apr_bucket_brigade *to);
/** /**
* Return a hash based on the passed string * Return a hash based on the passed string
* @param str string to produce hash from * @param str string to produce hash from

View File

@@ -1394,7 +1394,6 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
request_rec *rp; request_rec *rp;
apr_bucket *e; apr_bucket *e;
apr_bucket_brigade *bb, *tmp_bb; apr_bucket_brigade *bb, *tmp_bb;
apr_bucket_brigade *pass_bb;
int len, backasswards; int len, backasswards;
int interim_response = 0; /* non-zero whilst interim 1xx responses int interim_response = 0; /* non-zero whilst interim 1xx responses
* are being read. */ * are being read. */
@@ -1422,7 +1421,6 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
&& !(apr_table_get(r->subprocess_env, "force-proxy-request-1.0"))); && !(apr_table_get(r->subprocess_env, "force-proxy-request-1.0")));
bb = apr_brigade_create(p, c->bucket_alloc); bb = apr_brigade_create(p, c->bucket_alloc);
pass_bb = apr_brigade_create(p, c->bucket_alloc);
/* Setup for 100-Continue timeout if appropriate */ /* Setup for 100-Continue timeout if appropriate */
if (do_100_continue) { if (do_100_continue) {
@@ -1900,16 +1898,23 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
break; break;
} }
/* Switch the allocator lifetime of the buckets */
ap_proxy_buckets_lifetime_transform(r, bb, pass_bb);
apr_brigade_cleanup(bb);
/* found the last brigade? */ /* found the last brigade? */
if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(pass_bb))) { if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) {
/* signal that we must leave */ /* signal that we must leave */
finish = TRUE; finish = TRUE;
/* the brigade may contain transient buckets that contain
* data that lives only as long as the backend connection.
* Force a setaside so these transient buckets become heap
* buckets that live as long as the request.
*/
for (e = APR_BRIGADE_FIRST(bb); e
!= APR_BRIGADE_SENTINEL(bb); e
= APR_BUCKET_NEXT(e)) {
apr_bucket_setaside(e, r->pool);
}
/* make sure we release the backend connection as soon /* make sure we release the backend connection as soon
* as we know we are done, so that the backend isn't * as we know we are done, so that the backend isn't
* left waiting for a slow client to eventually * left waiting for a slow client to eventually
@@ -1921,7 +1926,7 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
} }
/* try send what we read */ /* try send what we read */
if (ap_pass_brigade(r->output_filters, pass_bb) != APR_SUCCESS if (ap_pass_brigade(r->output_filters, bb) != APR_SUCCESS
|| c->aborted) { || c->aborted) {
/* Ack! Phbtt! Die! User aborted! */ /* Ack! Phbtt! Die! User aborted! */
backend->close = 1; /* this causes socket close below */ backend->close = 1; /* this causes socket close below */
@@ -1929,7 +1934,7 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
} }
/* make sure we always clean up after ourselves */ /* make sure we always clean up after ourselves */
apr_brigade_cleanup(pass_bb); apr_brigade_cleanup(bb);
} while (!finish); } while (!finish);
} }

View File

@@ -2643,19 +2643,17 @@ PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function,
apr_sockaddr_t *backend_addr = conn->addr; apr_sockaddr_t *backend_addr = conn->addr;
int rc; int rc;
apr_interval_time_t current_timeout; apr_interval_time_t current_timeout;
apr_bucket_alloc_t *bucket_alloc;
if (conn->connection) { if (conn->connection) {
return OK; return OK;
} }
bucket_alloc = apr_bucket_alloc_create(conn->scpool);
/* /*
* The socket is now open, create a new backend server connection * The socket is now open, create a new backend server connection
*/ */
conn->connection = ap_run_create_connection(conn->scpool, s, conn->sock, conn->connection = ap_run_create_connection(conn->scpool, s, conn->sock,
0, NULL, 0, NULL,
bucket_alloc); c->bucket_alloc);
if (!conn->connection) { if (!conn->connection) {
/* /*
@@ -2742,56 +2740,6 @@ PROXY_DECLARE(void) ap_proxy_backend_broke(request_rec *r,
APR_BRIGADE_INSERT_TAIL(brigade, e); APR_BRIGADE_INSERT_TAIL(brigade, e);
} }
/*
* Transform buckets from one bucket allocator to another one by creating a
* transient bucket for each data bucket and let it use the data read from
* the old bucket. Metabuckets are transformed by just recreating them.
* Attention: Currently only the following bucket types are handled:
*
* All data buckets
* FLUSH
* EOS
*
* If an other bucket type is found its type is logged as a debug message
* and APR_EGENERAL is returned.
*/
PROXY_DECLARE(apr_status_t)
ap_proxy_buckets_lifetime_transform(request_rec *r, apr_bucket_brigade *from,
apr_bucket_brigade *to)
{
apr_bucket *e;
apr_bucket *new;
const char *data;
apr_size_t bytes;
apr_status_t rv = APR_SUCCESS;
apr_brigade_cleanup(to);
for (e = APR_BRIGADE_FIRST(from);
e != APR_BRIGADE_SENTINEL(from);
e = APR_BUCKET_NEXT(e)) {
if (!APR_BUCKET_IS_METADATA(e)) {
apr_bucket_read(e, &data, &bytes, APR_BLOCK_READ);
new = apr_bucket_transient_create(data, bytes, r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(to, new);
}
else if (APR_BUCKET_IS_FLUSH(e)) {
new = apr_bucket_flush_create(r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(to, new);
}
else if (APR_BUCKET_IS_EOS(e)) {
new = apr_bucket_eos_create(r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(to, new);
}
else {
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
"proxy: Unhandled bucket type of type %s in"
" ap_proxy_buckets_lifetime_transform", e->type->name);
rv = APR_EGENERAL;
}
}
return rv;
}
/* /*
* Provide a string hashing function for the proxy. * Provide a string hashing function for the proxy.
* We offer 2 methods: one is the APR model but we * We offer 2 methods: one is the APR model but we