ASF Bugzilla – Attachment 35870 Details for
Bug 62180
mod_xml2enc destroys error buckets
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
mod_xml2enc: pass all meta buckets down the chain (v3)
xml2enc_meta-v3.patch (text/plain), 27.44 KB, created by
Yann Ylavic
on 2018-04-12 22:42:15 UTC
(
hide
)
Description:
mod_xml2enc: pass all meta buckets down the chain (v3)
Filename:
MIME Type:
Creator:
Yann Ylavic
Created:
2018-04-12 22:42:15 UTC
Size:
27.44 KB
patch
obsolete
>Index: include/ap_mmn.h >=================================================================== >--- include/ap_mmn.h (revision 1828935) >+++ include/ap_mmn.h (working copy) >@@ -571,14 +571,18 @@ > * 20171014.7 (2.5.1-dev) Add AP_CORE_DEFAULT macro > * 20171014.8 (2.5.1-dev) Add CONN_STATE_NUM to enum conn_state_e > * 20171014.9 (2.5.1-dev) Add response_field_size to proxy_worker_shared >+ * 20180411.1 (2.5.1-dev) Add type ap_filters_ring_t, replace field 'filters' >+ * by the ap_filters_ring_t 'pending_filters' in struct >+ * conn_rec, and add ring entry 'pending' in struct >+ * ap_filter_t > */ > > #define MODULE_MAGIC_COOKIE 0x41503235UL /* "AP25" */ > > #ifndef MODULE_MAGIC_NUMBER_MAJOR >-#define MODULE_MAGIC_NUMBER_MAJOR 20171014 >+#define MODULE_MAGIC_NUMBER_MAJOR 20180411 > #endif >-#define MODULE_MAGIC_NUMBER_MINOR 9 /* 0...n */ >+#define MODULE_MAGIC_NUMBER_MINOR 1 /* 0...n */ > > /** > * Determine if the server's current MODULE_MAGIC_NUMBER is at least a >Index: include/http_protocol.h >=================================================================== >--- include/http_protocol.h (revision 1828935) >+++ include/http_protocol.h (working copy) >@@ -631,7 +631,9 @@ AP_DECLARE(apr_status_t) ap_get_basic_auth_compone > AP_CORE_DECLARE(void) ap_parse_uri(request_rec *r, const char *uri); > > #define AP_GETLINE_FOLD 1 /* Whether to merge continuation lines */ >-#define AP_GETLINE_CRLF 2 /*Whether line ends must be in the form CR LF */ >+#define AP_GETLINE_CRLF 2 /* Whether line ends must be in the form CR LF */ >+#define AP_GETLINE_NOSPC_EOL 4 /* Whether to consume up to and including the >+ end of line on APR_ENOSPC */ > > /** > * Get the next line of input for the request >Index: include/httpd.h >=================================================================== >--- include/httpd.h (revision 1828935) >+++ include/httpd.h (working copy) >@@ -1224,8 +1224,8 @@ struct conn_rec { > /** Empty bucket brigade */ > apr_bucket_brigade *empty; > >- /** Hashtable of filters with setaside buckets for write completion */ >- apr_hash_t *filters; >+ /** Ring of pending filters (with setaside buckets) */ >+ struct ap_filters_ring *pending_filters; > > /** The minimum level of filter type to allow setaside buckets */ > int async_filter; >Index: include/util_filter.h >=================================================================== >--- include/util_filter.h (revision 1828935) >+++ include/util_filter.h (working copy) >@@ -299,9 +299,16 @@ struct ap_filter_t { > /** Dedicated pool to use for deferred writes. */ > apr_pool_t *deferred_pool; > >+ /** Entry in ring of pending filters (with setaside buckets). */ >+ APR_RING_ENTRY(ap_filter_t) pending; > }; > > /** >+ * @brief The representation of a filters' ring. >+ */ >+typedef APR_RING_HEAD(ap_filters_ring, ap_filter_t) ap_filters_ring_t; >+ >+/** > * Get the current bucket brigade from the next filter on the filter > * stack. The filter returns an apr_status_t value. If the bottom-most > * filter doesn't read from the network, then ::AP_NOBODY_READ is returned. >Index: modules/filters/mod_xml2enc.c >=================================================================== >--- modules/filters/mod_xml2enc.c (revision 1828935) >+++ modules/filters/mod_xml2enc.c (working copy) >@@ -309,6 +309,7 @@ static apr_status_t xml2enc_ffunc(ap_filter_t* f, > apr_bucket* b; > apr_bucket* bstart; > apr_size_t insz = 0; >+ int pending_meta = 0; > char *ctype; > char *p; > >@@ -400,16 +401,34 @@ static apr_status_t xml2enc_ffunc(ap_filter_t* f, > ctx->bytes = 0; > if (APR_BUCKET_IS_METADATA(b)) { > APR_BUCKET_REMOVE(b); >+ APR_BRIGADE_INSERT_TAIL(ctx->bbnext, b); >+ /* This resource filter is over on EOS */ > if (APR_BUCKET_IS_EOS(b)) { >- /* send remaining data */ >- APR_BRIGADE_INSERT_TAIL(ctx->bbnext, b); >- return ap_fflush(f->next, ctx->bbnext); >- } else if (APR_BUCKET_IS_FLUSH(b)) { >- ap_fflush(f->next, ctx->bbnext); >+ ap_remove_output_filter(f); >+ rv = ap_pass_brigade(f->next, ctx->bbnext); >+ apr_brigade_cleanup(ctx->bbnext); >+ return rv; > } >- apr_bucket_destroy(b); >+ /* Besides FLUSH, aggregate meta buckets to send >+ * them at once below. >+ */ >+ pending_meta = 1; >+ if (!APR_BUCKET_IS_FLUSH(b)) { >+ continue; >+ } > } >- else { /* data bucket */ >+ if (pending_meta) { >+ pending_meta = 0; >+ /* passing meta bucket down the chain */ >+ rv = ap_pass_brigade(f->next, ctx->bbnext); >+ apr_brigade_cleanup(ctx->bbnext); >+ if (rv != APR_SUCCESS) { >+ return rv; >+ } >+ continue; >+ } >+ /* data bucket */ >+ { > char* buf; > apr_size_t bytes = 0; > char fixbuf[BUFLEN]; >@@ -514,8 +533,7 @@ static apr_status_t xml2enc_ffunc(ap_filter_t* f, > if (rv != APR_SUCCESS) > ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, f->r, APLOGNO(01446) > "ap_fflush failed"); >- else >- rv = ap_pass_brigade(f->next, ctx->bbnext); >+ apr_brigade_cleanup(ctx->bbnext); > } > } > } else { >Index: modules/proxy/mod_proxy_http.c >=================================================================== >--- modules/proxy/mod_proxy_http.c (revision 1828935) >+++ modules/proxy/mod_proxy_http.c (working copy) >@@ -32,8 +32,8 @@ static apr_status_t ap_proxygetline(apr_bucket_bri > char *s, > int n, > request_rec *r, >- int fold, >- int *writen); >+ int flags, >+ int *read); > > /* > * Canonicalise http-like URLs. >@@ -1098,7 +1098,6 @@ static void ap_proxy_read_headers(request_rec *r, > { > int len; > char *value, *end; >- char field[MAX_STRING_LEN]; > int saw_headers = 0; > void *sconf = r->server->module_config; > proxy_server_conf *psc; >@@ -1122,12 +1121,24 @@ static void ap_proxy_read_headers(request_rec *r, > > tmp_bb = apr_brigade_create(r->pool, c->bucket_alloc); > while (1) { >- rc = ap_proxygetline(tmp_bb, buffer, size, rr, 1, &len); >- >+ rc = ap_proxygetline(tmp_bb, buffer, size, rr, >+ AP_GETLINE_FOLD | AP_GETLINE_NOSPC_EOL, >+ &len); > if (len <= 0) > break; > >- ap_log_rerror(APLOG_MARK, APLOG_TRACE4, 0, r, "%s", buffer); >+ if (APR_STATUS_IS_ENOSPC(rc)) { >+ /* The header could not fit in the provided buffer, warn. >+ * XXX: falls through with the truncated header, shouldn't we 502? >+ */ >+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, rc, r, APLOGNO(10124) >+ "header size is over the limit allowed by ResponseFieldSize (%d bytes). " >+ "Bad response header '%s': '%.*s'...", >+ size, buffer, 80, value); >+ } >+ else { >+ ap_log_rerror(APLOG_MARK, APLOG_TRACE4, 0, r, "%s", buffer); >+ } > > if (!(value = strchr(buffer, ':'))) { /* Find the colon separator */ > >@@ -1195,28 +1206,6 @@ static void ap_proxy_read_headers(request_rec *r, > */ > process_proxy_header(r, dconf, buffer, value); > saw_headers = 1; >- >- /* The header could not fit in the provided buffer. */ >- if (rc == APR_ENOSPC) { >- ap_log_rerror(APLOG_MARK, APLOG_WARNING, rc, r, APLOGNO(10124) >- "header size is over the limit allowed by ResponseFieldSize (%d bytes). " >- "Bad response header '%s': '%.*s'...", >- size, buffer, 80, value); >- >- /* XXX: We overran the limit we passed to ap_rgetline_core, but if the length >- * exceeded the limit by a small amount, it may have already been consumed >- * by apr_brigade_split_line called from the core input filter. If that >- * happens, this loop will throw away the next full line (header) instead of >- * the remainder of the current long header. >- */ >- while ((len = ap_getline(field, MAX_STRING_LEN, rr, 1)) >- >= MAX_STRING_LEN - 1) { >- /* soak up the extra data */ >- } >- >- if (len == 0) /* time to exit the larger loop as well */ >- break; >- } > } > } > >@@ -1230,21 +1219,19 @@ static int addit_dammit(void *v, const char *key, > > static > apr_status_t ap_proxygetline(apr_bucket_brigade *bb, char *s, int n, request_rec *r, >- int fold, int *writen) >+ int flags, int *read) > { > char *tmp_s = s; > apr_status_t rv; > apr_size_t len; > >- rv = ap_rgetline(&tmp_s, n, &len, r, fold, bb); >+ rv = ap_rgetline_core(&tmp_s, n, &len, r, flags, bb); > apr_brigade_cleanup(bb); > >- if (rv == APR_SUCCESS) { >- *writen = (int) len; >- } else if (APR_STATUS_IS_ENOSPC(rv)) { >- *writen = n; >+ if (rv == APR_SUCCESS || APR_STATUS_IS_ENOSPC(rv)) { >+ *read = (int)len; > } else { >- *writen = -1; >+ *read = -1; > } > > return rv; >Index: modules/proxy/proxy_util.c >=================================================================== >--- modules/proxy/proxy_util.c (revision 1828935) >+++ modules/proxy/proxy_util.c (working copy) >@@ -1478,29 +1478,41 @@ static apr_status_t connection_cleanup(void *theco > > /* determine if the connection need to be closed */ > if (!worker->s->is_address_reusable || worker->s->disablereuse) { >- apr_pool_t *p = conn->pool; >- apr_pool_clear(p); >- conn = apr_pcalloc(p, sizeof(proxy_conn_rec)); >- conn->pool = p; >- conn->worker = worker; >- apr_pool_create(&(conn->scpool), p); >- apr_pool_tag(conn->scpool, "proxy_conn_scpool"); >+ if (worker->s->hmax && worker->cp->res) { >+ apr_reslist_invalidate(worker->cp->res, conn); >+ } >+ else { >+ apr_pool_t *p = conn->pool; >+ apr_pool_clear(p); >+ conn = apr_pcalloc(p, sizeof(proxy_conn_rec)); >+ conn->pool = p; >+ conn->worker = worker; >+ apr_pool_create(&(conn->scpool), p); >+ apr_pool_tag(conn->scpool, "proxy_conn_scpool"); >+ worker->cp->conn = conn; >+ } > } > else if (conn->close > || (conn->connection > && conn->connection->keepalive == AP_CONN_CLOSE)) { >- socket_cleanup(conn); >- conn->close = 0; >+ if (worker->s->hmax && worker->cp->res) { >+ apr_reslist_invalidate(worker->cp->res, conn); >+ } >+ else { >+ socket_cleanup(conn); >+ conn->close = 0; >+ worker->cp->conn = conn; >+ } > } >- >- if (worker->s->hmax && worker->cp->res) { >- conn->inreslist = 1; >- apr_reslist_release(worker->cp->res, (void *)conn); >+ else { >+ if (worker->s->hmax && worker->cp->res) { >+ conn->inreslist = 1; >+ apr_reslist_release(worker->cp->res, conn); >+ } >+ else { >+ worker->cp->conn = conn; >+ } > } >- else >- { >- worker->cp->conn = conn; >- } > > /* Always return the SUCCESS */ > return APR_SUCCESS; >Index: modules/ssl/ssl_engine_config.c >=================================================================== >--- modules/ssl/ssl_engine_config.c (revision 1828935) >+++ modules/ssl/ssl_engine_config.c (working copy) >@@ -40,7 +40,7 @@ > ** _________________________________________________________________ > */ > >-#define SSL_MOD_CONFIG_KEY "ssl_module" >+#define MODSSL_CONFIG_KEY "ssl_module" > > SSLModConfigRec *ssl_config_global_create(server_rec *s) > { >@@ -48,7 +48,7 @@ SSLModConfigRec *ssl_config_global_create(server_r > SSLModConfigRec *mc; > void *vmc; > >- apr_pool_userdata_get(&vmc, SSL_MOD_CONFIG_KEY, pool); >+ apr_pool_userdata_get(&vmc, MODSSL_CONFIG_KEY, pool); > if (vmc) { > return vmc; /* reused for lifetime of the server */ > } >@@ -79,7 +79,7 @@ SSLModConfigRec *ssl_config_global_create(server_r > mc->stapling_refresh_mutex = NULL; > #endif > >- apr_pool_userdata_set(mc, SSL_MOD_CONFIG_KEY, >+ apr_pool_userdata_set(mc, MODSSL_CONFIG_KEY, > apr_pool_cleanup_null, > pool); > >@@ -542,7 +542,7 @@ static apr_hash_t *get_policies(apr_pool_t *p, int > apr_hash_t *policies; > void *vp; > >- apr_pool_userdata_get(&vp, SSL_MOD_POLICIES_KEY, p); >+ apr_pool_userdata_get(&vp, MODSSL_POLICIES_KEY, p); > if (vp) { > return vp; /* reused for lifetime of the pool */ > } >@@ -577,7 +577,7 @@ static apr_hash_t *get_policies(apr_pool_t *p, int > SSL_POLICY_SESSION_TICKETS); > #endif > >- apr_pool_userdata_set(policies, SSL_MOD_POLICIES_KEY, >+ apr_pool_userdata_set(policies, MODSSL_POLICIES_KEY, > apr_pool_cleanup_null, p); > return policies; > } >Index: modules/ssl/ssl_policies.h >=================================================================== >--- modules/ssl/ssl_policies.h (revision 1828935) >+++ modules/ssl/ssl_policies.h (working copy) >@@ -34,7 +34,7 @@ > #ifndef __SSL_POLICIES_H__ > #define __SSL_POLICIES_H__ > >-#define SSL_MOD_POLICIES_KEY "ssl_module_policies" >+#define MODSSL_POLICIES_KEY "ssl_module_policies" > > #ifndef OPENSSL_NO_SSL3 > #define SSL_PROTOCOL_CONSTANTS_SSLV3 SSL_PROTOCOL_SSLV3 >Index: os/unix/unixd.c >=================================================================== >--- os/unix/unixd.c (revision 1828935) >+++ os/unix/unixd.c (working copy) >@@ -516,7 +516,7 @@ static apr_status_t unset_signals(void *unused) > return APR_SUCCESS; > } > >-static void ap_terminate(void) >+static void ap_unixd_terminate(void) > { > ap_main_state = AP_SQ_MS_EXITING; > apr_pool_destroy(ap_pglobal); >@@ -532,12 +532,9 @@ AP_DECLARE(void) ap_unixd_mpm_set_signals(apr_pool > if (!one_process) { > ap_fatal_signal_setup(ap_server_conf, pconf); > } >- else { >- static int once = 0; >- if (!once) { >- atexit(ap_terminate); >- once = 1; >- } >+ else if (!ap_retained_data_get("ap_unixd_terminate")) { >+ ap_retained_data_create("ap_unixd_terminate", 1); >+ atexit(ap_unixd_terminate); > } > > /* Signals' handlers depend on retained data */ >Index: server/core.c >=================================================================== >--- server/core.c (revision 1828935) >+++ server/core.c (working copy) >@@ -5318,7 +5318,6 @@ static conn_rec *core_create_conn(apr_pool_t *ptra > c->id = id; > c->bucket_alloc = alloc; > c->empty = apr_brigade_create(c->pool, c->bucket_alloc); >- c->filters = apr_hash_make(c->pool); > c->async_filter = sconf->async_filter; > > c->clogging_input_filters = 0; >Index: server/protocol.c >=================================================================== >--- server/protocol.c (revision 1828935) >+++ server/protocol.c (working copy) >@@ -224,6 +224,8 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s > int do_alloc = (*s == NULL), saw_eos = 0; > int fold = flags & AP_GETLINE_FOLD; > int crlf = flags & AP_GETLINE_CRLF; >+ int nospc_eol = flags & AP_GETLINE_NOSPC_EOL; >+ int eol = 0; > > if (!n) { > /* Needs room for NUL byte at least */ >@@ -239,7 +241,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s > if (last_char) > *last_char = '\0'; > >- for (;;) { >+ do { > apr_brigade_cleanup(bb); > rv = ap_get_brigade(r->proto_input_filters, bb, AP_MODE_GETLINE, > APR_BLOCK_READ, 0); >@@ -283,8 +285,19 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s > > /* Would this overrun our buffer? If so, we'll die. */ > if (n < bytes_handled + len) { >+ /* But before we'll fill in the buffer up to its limit (i.e. >+ * fall through with the remaining length if necessary), and >+ * optionally consume the full line until LF (nospc_eol). >+ */ > rv = APR_ENOSPC; >- goto cleanup; >+ eol = (str[len - 1] == APR_ASCII_LF); >+ len = n - bytes_handled; >+ if (!len) { >+ if (nospc_eol) { >+ continue; >+ } >+ goto cleanup; >+ } > } > > /* Do we have to handle the allocation ourselves? */ >@@ -323,8 +336,13 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s > > /* If we got a full line of input, stop reading */ > if (last_char && (*last_char == APR_ASCII_LF)) { >- break; >+ eol = 1; > } >+ } while (!eol); >+ >+ if (rv != APR_SUCCESS) { >+ /* End of line after APR_ENOSPC above */ >+ goto cleanup; > } > > /* Now terminate the string at the end of the line; >Index: server/util.c >=================================================================== >--- server/util.c (revision 1828935) >+++ server/util.c (working copy) >@@ -185,55 +185,93 @@ AP_DECLARE(char *) ap_ht_time(apr_pool_t *p, apr_t > * Based loosely on sections of wildmat.c by Rich Salz > * Hmmm... shouldn't this really go component by component? > */ >-AP_DECLARE(int) ap_strcmp_match(const char *str, const char *expected) >+#if 1 >+static int ap_strcmp_match_r(const char *str, const char *expected, >+ apr_size_t xstart, apr_size_t ystart, >+ int nocase) > { >- int x, y; >+ apr_size_t x, y; > >- for (x = 0, y = 0; expected[y]; ++y, ++x) { >+ do { >+ x = xstart++; >+ for (y = ystart; expected[y]; ++y, ++x) { > if (expected[y] == '*') { > while (expected[++y] == '*'); > if (!expected[y]) > return 0; >- while (str[x]) { >- int ret; >- if ((ret = ap_strcmp_match(&str[x++], &expected[y])) != 1) >- return ret; >+ if (str[x]) { >+ return ap_strcmp_match_r(str, expected, x, y, nocase); > } > return -1; > } > else if (!str[x]) > return -1; >- else if ((expected[y] != '?') && (str[x] != expected[y])) >+ else if ((expected[y] != '?') && (str[x] != expected[y]) && >+ (!nocase || apr_tolower(str[x]) != apr_tolower(expected[y]))) > return 1; > } >- return (str[x] != '\0'); >+ if (!str[x]) >+ return 0; >+ } while (ystart); >+ >+ return 1; > } > >+AP_DECLARE(int) ap_strcmp_match(const char *str, const char *expected) >+{ >+ return ap_strcmp_match_r(str, expected, 0, 0, 0); >+} >+ > AP_DECLARE(int) ap_strcasecmp_match(const char *str, const char *expected) > { >- int x, y; >+ return ap_strcmp_match_r(str, expected, 0, 0, 1); >+} >+#else >+#define MATCH_NC 0x1 >+#define MATCH_REC 0x2 >+static int ap_strcmp_match_r(const char *str, const char *expected, int flags) >+{ >+ const char *x, *y; > >- for (x = 0, y = 0; expected[y]; ++y, ++x) { >- if (!str[x] && expected[y] != '*') >- return -1; >- if (expected[y] == '*') { >- while (expected[++y] == '*'); >- if (!expected[y]) >- return 0; >- while (str[x]) { >- int ret; >- if ((ret = ap_strcasecmp_match(&str[x++], &expected[y])) != 1) >- return ret; >+ do { >+ x = str++; >+ for (y = expected; *y; ++y, ++x) { >+ if (*y == '*') { >+ do { >+ ++y; >+ } while (*y == '*'); >+ if (!*y) >+ return 0; >+ if (!*x) >+ return -1; >+ return ap_strcmp_match_r(x, y, flags | MATCH_REC); > } >- return -1; >+ else if (!*x) >+ return -1; >+ else if ((*y != '?') >+ && (*x != *y) >+ && (!(flags & MATCH_NC) >+ || apr_tolower(*x) != apr_tolower(*y))) >+ return 1; > } >- else if (expected[y] != '?' >- && apr_tolower(str[x]) != apr_tolower(expected[y])) >- return 1; >- } >- return (str[x] != '\0'); >+ if (!*x) >+ return 0; >+ } while (flags & MATCH_REC); >+ >+ return 1; > } > >+AP_DECLARE(int) ap_strcmp_match(const char *str, const char *expected) >+{ >+ return ap_strcmp_match_r(str, expected, 0); >+} >+ >+AP_DECLARE(int) ap_strcasecmp_match(const char *str, const char *expected) >+{ >+ return ap_strcmp_match_r(str, expected, MATCH_NC); >+} >+#endif >+ > /* We actually compare the canonical root to this root, (but we don't > * waste time checking the case), since every use of this function in > * httpd-2.1 tests if the path is 'proper', meaning we've already passed >Index: server/util_filter.c >=================================================================== >--- server/util_filter.c (revision 1828935) >+++ server/util_filter.c (working copy) >@@ -293,7 +293,7 @@ static ap_filter_t *add_any_filter_handle(ap_filte > ap_filter_t **c_filters) > { > apr_pool_t *p = frec->ftype < AP_FTYPE_CONNECTION && r ? r->pool : c->pool; >- ap_filter_t *f = apr_palloc(p, sizeof(*f)); >+ ap_filter_t *f = apr_pcalloc(p, sizeof(*f)); > ap_filter_t **outf; > > if (frec->ftype < AP_FTYPE_PROTOCOL) { >@@ -325,9 +325,7 @@ static ap_filter_t *add_any_filter_handle(ap_filte > /* f->r must always be NULL for connection filters */ > f->r = frec->ftype < AP_FTYPE_CONNECTION ? r : NULL; > f->c = c; >- f->next = NULL; >- f->bb = NULL; >- f->deferred_pool = NULL; >+ APR_RING_ELEM_INIT(f, pending); > > if (INSERT_BEFORE(f, *outf)) { > f->next = *outf; >@@ -451,6 +449,23 @@ AP_DECLARE(ap_filter_t *) ap_add_output_filter_han > &c->output_filters); > } > >+static APR_INLINE int is_pending_filter(ap_filter_t *f) >+{ >+ return APR_RING_NEXT(f, pending) != f; >+} >+ >+static apr_status_t pending_filter_cleanup(void *arg) >+{ >+ ap_filter_t *f = arg; >+ >+ if (is_pending_filter(f)) { >+ APR_RING_REMOVE(f, pending); >+ APR_RING_ELEM_INIT(f, pending); >+ } >+ >+ return APR_SUCCESS; >+} >+ > static void remove_any_filter(ap_filter_t *f, ap_filter_t **r_filt, ap_filter_t **p_filt, > ap_filter_t **c_filt) > { >@@ -457,6 +472,8 @@ static void remove_any_filter(ap_filter_t *f, ap_f > ap_filter_t **curr = r_filt ? r_filt : c_filt; > ap_filter_t *fscan = *curr; > >+ pending_filter_cleanup(f); >+ > if (p_filt && *p_filt == f) > *p_filt = (*p_filt)->next; > >@@ -695,39 +712,55 @@ AP_DECLARE(apr_status_t) ap_save_brigade(ap_filter > return srv; > } > >-static apr_status_t filters_cleanup(void *data) >-{ >- ap_filter_t **key = data; >- >- apr_hash_set((*key)->c->filters, key, sizeof *key, NULL); >- >- return APR_SUCCESS; >-} >- > AP_DECLARE(int) ap_filter_prepare_brigade(ap_filter_t *f, apr_pool_t **p) > { > apr_pool_t *pool; >- ap_filter_t **key; >+ ap_filter_t *found = NULL; >+ ap_filter_t *next, *e; > >+ pool = f->r ? f->r->pool : f->c->pool; >+ if (p) { >+ *p = pool; >+ } > if (!f->bb) { >- >- pool = f->r ? f->r->pool : f->c->pool; >- >- key = apr_pmemdup(pool, &f, sizeof f); >- apr_hash_set(f->c->filters, key, sizeof *key, f); >- > f->bb = apr_brigade_create(pool, f->c->bucket_alloc); >+ apr_pool_pre_cleanup_register(pool, f, pending_filter_cleanup); >+ } >+ if (is_pending_filter(f)) { >+ return DECLINED; >+ } > >- apr_pool_pre_cleanup_register(pool, key, filters_cleanup); >- >- if (p) { >- *p = pool; >+ /* Pending reads/writes must happen in the same order as input/output >+ * filters, so order this filter in both chains accordingly. Find the >+ * first "next" filter already in place and insert before it, if any, >+ * otherwise insert last. >+ */ >+ if (f->c->pending_filters) { >+ for (next = f->next; next && !found; next = next->next) { >+ for (e = APR_RING_FIRST(f->c->pending_filters); >+ e != APR_RING_SENTINEL(f->c->pending_filters, >+ ap_filter_t, pending); >+ e = APR_RING_NEXT(e, pending)) { >+ if (e == next) { >+ found = e; >+ break; >+ } >+ } > } >- >- return OK; > } >- >- return DECLINED; >+ else { >+ f->c->pending_filters = apr_palloc(f->c->pool, >+ sizeof *f->c->pending_filters); >+ APR_RING_INIT(f->c->pending_filters, ap_filter_t, pending); >+ } >+ if (found) { >+ APR_RING_INSERT_BEFORE(found, f, pending); >+ } >+ else { >+ APR_RING_INSERT_TAIL(f->c->pending_filters, f, ap_filter_t, pending); >+ } >+ >+ return OK; > } > > AP_DECLARE(apr_status_t) ap_filter_setaside_brigade(ap_filter_t *f, >@@ -967,23 +1000,24 @@ AP_DECLARE(int) ap_filter_should_yield(ap_filter_t > > AP_DECLARE(int) ap_filter_output_pending(conn_rec *c) > { >- apr_hash_index_t *rindex; > int data_in_output_filters = DECLINED; >+ ap_filter_t *f; > >- rindex = apr_hash_first(NULL, c->filters); >- while (rindex) { >- ap_filter_t *f = apr_hash_this_val(rindex); >+ if (!c->pending_filters) { >+ return DECLINED; >+ } > >+ for (f = APR_RING_FIRST(c->pending_filters); >+ f != APR_RING_SENTINEL(c->pending_filters, ap_filter_t, pending); >+ f = APR_RING_NEXT(f, pending)) { > if (f->frec->direction == AP_FILTER_OUTPUT && f->bb > && !APR_BRIGADE_EMPTY(f->bb)) { >- > apr_status_t rv; > > rv = ap_pass_brigade(f, c->empty); > apr_brigade_cleanup(c->empty); >- if (APR_SUCCESS != rv) { >- ap_log_cerror( >- APLOG_MARK, APLOG_DEBUG, rv, c, APLOGNO(00470) >+ if (rv != APR_SUCCESS && !APR_STATUS_IS_EAGAIN(rv)) { >+ ap_log_cerror(APLOG_MARK, APLOG_DEBUG, rv, c, APLOGNO(00470) > "write failure in '%s' output filter", f->frec->name); > return rv; > } >@@ -992,8 +1026,6 @@ AP_DECLARE(int) ap_filter_output_pending(conn_rec > data_in_output_filters = OK; > } > } >- >- rindex = apr_hash_next(rindex); > } > > return data_in_output_filters; >@@ -1001,12 +1033,15 @@ AP_DECLARE(int) ap_filter_output_pending(conn_rec > > AP_DECLARE(int) ap_filter_input_pending(conn_rec *c) > { >- apr_hash_index_t *rindex; >+ ap_filter_t *f; > >- rindex = apr_hash_first(NULL, c->filters); >- while (rindex) { >- ap_filter_t *f = apr_hash_this_val(rindex); >+ if (!c->pending_filters) { >+ return DECLINED; >+ } > >+ for (f = APR_RING_FIRST(c->pending_filters); >+ f != APR_RING_SENTINEL(c->pending_filters, ap_filter_t, pending); >+ f = APR_RING_NEXT(f, pending)) { > if (f->frec->direction == AP_FILTER_INPUT && f->bb) { > apr_bucket *e = APR_BRIGADE_FIRST(f->bb); > >@@ -1019,8 +1054,6 @@ AP_DECLARE(int) ap_filter_input_pending(conn_rec * > } > > } >- >- rindex = apr_hash_next(rindex); > } > > return DECLINED;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 62180
:
35769
|
35770
|
35869
|
35870
|
35871
|
35872