On Wed, Apr 26, 2017 at 11:26 AM, Stefan Eissing
<[email protected]> wrote:
>
>> Am 26.04.2017 um 11:14 schrieb Plüm, Rüdiger, Vodafone Group
>> <[email protected]>:
>>
>>
>>
>>> -----Ursprüngliche Nachricht-----
>>> Von: Stefan Eissing [mailto:[email protected]]
>>> Gesendet: Mittwoch, 26. April 2017 10:55
>>> An: [email protected]
>>> Betreff: Re: svn commit: r1707087 -
>>> /httpd/httpd/trunk/modules/debugging/mod_bucketeer.c
>>>
>>> Eh, not really into mod_bucketeer and its use cases, but some
>>> observations after a quick scan:
>>>
>>> line 99:
>>> rv = ap_pass_brigade(f->next, ctx->bb);
>>> apr_brigade_cleanup(ctx->bb);
>>>
>>> line 146:
>>> rv = ap_pass_brigade(f->next, ctx->bb);
>>> if (rv) {
>>> return rv;
>>> }
>>> apr_brigade_cleanup(ctx->bb);
>>>
>>> such things only work if an EOS always comes *before* an EOR
>>> bucket (case 1) or of no DATA bucket of any kind follows an EOR.
>>
>> Correct, but with the BUCKETEER filter being a resource filter that
>> should not happen.
>
> Because the implementations of everything else in the server do not
> do it? Should we then add a filter that checks exactly that?
I don't think that EOR before EOS can happen in HTTP/1, because
ap_finalize_request_protocol() is always called before
ap_process_request_after_handler().
EOS is the signal for request filters to get out of the way, so this
is probably what ap_request_core_filter() should do too, and the
purpose of the attached patch.
This patch could use EOR instead, but I find EOS more "semantically"
correct for a request filter (we don't need to set aside anything
after it), while EOR would be crash safe only...
Jacob, does it work better?
Regards,
Yann.
Index: server/request.c
===================================================================
--- server/request.c (revision 1791747)
+++ server/request.c (working copy)
@@ -2057,12 +2057,27 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_request_co
tmp_bb = f->ctx = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
}
+ /* Use the given bb downstream (purposedly scoped), hence move the
+ * buckets into tmp_bb to walk through them locally.
+ */
+ APR_BRIGADE_CONCAT(tmp_bb, bb);
+
/* Reinstate any buffered content */
- ap_filter_reinstate_brigade(f, bb, &flush_upto);
+ ap_filter_reinstate_brigade(f, tmp_bb, &flush_upto);
- while (!APR_BRIGADE_EMPTY(bb)) {
- apr_bucket *bucket = APR_BRIGADE_FIRST(bb);
+ while (!APR_BRIGADE_EMPTY(tmp_bb)) {
+ apr_bucket *bucket = APR_BRIGADE_FIRST(tmp_bb);
+ int eos = APR_BUCKET_IS_EOS(bucket);
+ if (eos) {
+ /* pass everything down the chain, this request is over (and will
+ * possibly be destroyed before we leave, should the EOR be aside),
+ * not this filter's business anymore.
+ */
+ APR_BRIGADE_CONCAT(bb, tmp_bb);
+ ap_remove_output_filter(f);
+ }
+ else {
/* if the core has set aside data, back off and try later */
if (!flush_upto) {
if (ap_filter_should_yield(f)) {
@@ -2088,20 +2103,19 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_request_co
}
}
}
-
/* pass each bucket down the chain */
APR_BUCKET_REMOVE(bucket);
- APR_BRIGADE_INSERT_TAIL(tmp_bb, bucket);
+ APR_BRIGADE_INSERT_TAIL(bb, bucket);
+ }
- status = ap_pass_brigade(f->next, tmp_bb);
- if (!APR_STATUS_IS_EOF(status) && (status != APR_SUCCESS)) {
+ status = ap_pass_brigade(f->next, bb);
+ if (status != APR_SUCCESS || eos) {
return status;
}
-
+ apr_brigade_cleanup(bb);
}
- ap_filter_setaside_brigade(f, bb);
- return status;
+ return ap_filter_setaside_brigade(f, tmp_bb);
}
extern APR_OPTIONAL_FN_TYPE(authz_some_auth_required) *ap__authz_ap_some_auth_required;