You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by yl...@apache.org on 2018/08/10 16:15:50 UTC
svn commit: r1837822 - /httpd/httpd/trunk/server/util_filter.c
Author: ylavic
Date: Fri Aug 10 16:15:50 2018
New Revision: 1837822
URL: http://svn.apache.org/viewvc?rev=1837822&view=rev
Log:
core: ap_filter_output_pending() to flush outer most filters first.
Since previous output filters may use ap_filter_should_yield() to determine
whether they should send more data (e.g. ap_request_core_filter), we need
to flush pending data from the core output filter first, and so on up the
chain.
Otherwise we may enter an infinite loop where ap_request_core_filter() does
nothing on ap_filter_output_pending() called from MPM event.
Modified:
httpd/httpd/trunk/server/util_filter.c
Modified: httpd/httpd/trunk/server/util_filter.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/util_filter.c?rev=1837822&r1=1837821&r2=1837822&view=diff
==============================================================================
--- httpd/httpd/trunk/server/util_filter.c (original)
+++ httpd/httpd/trunk/server/util_filter.c Fri Aug 10 16:15:50 2018
@@ -818,6 +818,12 @@ AP_DECLARE(apr_status_t) ap_filter_reins
int eor_buckets_in_brigade, morphing_bucket_in_brigade;
core_server_config *conf;
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE6, 0, f->c,
+ "reinstate %s brigade to %s brigade in '%s' output filter",
+ (!f->bb || APR_BRIGADE_EMPTY(f->bb) ? "empty" : "full"),
+ (APR_BRIGADE_EMPTY(bb) ? "empty" : "full"),
+ f->frec->name);
+
if (f->bb && !APR_BRIGADE_EMPTY(f->bb)) {
APR_BRIGADE_PREPEND(bb, f->bb);
}
@@ -828,12 +834,6 @@ AP_DECLARE(apr_status_t) ap_filter_reins
*flush_upto = NULL;
- ap_log_cerror(APLOG_MARK, APLOG_TRACE6, 0, f->c,
- "reinstate %s brigade to %s brigade in '%s' output filter",
- (!f->bb || APR_BRIGADE_EMPTY(f->bb) ? "empty" : "full"),
- (APR_BRIGADE_EMPTY(bb) ? "empty" : "full"),
- f->frec->name);
-
/*
* Determine if and up to which bucket we need to do a blocking write:
*
@@ -1005,9 +1005,13 @@ AP_DECLARE_NONSTD(int) ap_filter_output_
bb = ap_reuse_brigade_from_pool("ap_fop_bb", c->pool,
c->bucket_alloc);
- for (f = APR_RING_FIRST(c->pending_filters);
+ /* Flush outer most filters first for ap_filter_should_yield(f->next)
+ * to be relevant in the previous ones (e.g. ap_request_core_filter()
+ * won't pass its buckets if its next filters yields already).
+ */
+ for (f = APR_RING_LAST(c->pending_filters);
f != APR_RING_SENTINEL(c->pending_filters, ap_filter_t, pending);
- f = APR_RING_NEXT(f, pending)) {
+ f = APR_RING_PREV(f, pending)) {
if (f->frec->direction == AP_FILTER_OUTPUT && f->bb
&& !APR_BRIGADE_EMPTY(f->bb)) {
apr_status_t rv;
@@ -1038,9 +1042,9 @@ AP_DECLARE_NONSTD(int) ap_filter_input_p
return DECLINED;
}
- for (f = APR_RING_FIRST(c->pending_filters);
+ for (f = APR_RING_LAST(c->pending_filters);
f != APR_RING_SENTINEL(c->pending_filters, ap_filter_t, pending);
- f = APR_RING_NEXT(f, pending)) {
+ f = APR_RING_PREV(f, pending)) {
if (f->frec->direction == AP_FILTER_INPUT && f->bb) {
apr_bucket *e = APR_BRIGADE_FIRST(f->bb);