Though these things aren't documented, it's been repeated here many times that there should be only one EOS bucket seen by filters. I'm working on several filter examples and to protect my filters from the bad behavior of other filters I see no other choice but maintaining my own eos_sent flag in the filter context. Unfortunately this adds clutter to the code, but what can I do.

The latest cvs version of ap_http_filter sends the EOS bucket twice. I see the following in my input request (resource) filter that happens to read some POSTed data.

bb1: [data] [eos]
bb2: [eos]

We are now in http_protocol.c: ap_http_filter.

The first eos is tacked here:

/* If we have no more bytes remaining on a C-L request,
* save the caller a roundtrip to discover EOS.
*/
if (ctx->state == BODY_LENGTH && ctx->remaining == 0) {
e = apr_bucket_eos_create(f->c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(b, e);
}

notice that ctx->eos_sent is *not* set, which IMHO is wrong. Moreover all other code in ap_http_filter never checks whether ctx->eos_sent is set.

I've tried to add the missing checks, but it breaks, because the roundtrip happens all the time, even though there is no more data and if you don't send EOS down the stream but just return APR_SUCCESS in:

if (!ctx->remaining) {
switch (ctx->state) {
case BODY_NONE:
break;
case BODY_LENGTH:
if (ctx->eos_sent == 0) {
ctx->eos_sent = 1;
e = apr_bucket_eos_create(f->c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(b, e);
}
return APR_SUCCESS;
...

the whole mechanism breaks. So currently the only simple fix I see is not to try to save the round trip:

if (ctx->state == BODY_LENGTH && ctx->remaining == 0) {
/* e = apr_bucket_eos_create(f->c->bucket_alloc); */
/* APR_BRIGADE_INSERT_TAIL(b, e); */
}

Why the round trip happens again? After all there is no more data left in the pipe.

You can easily see the too many EOS sends by breaking at apr_bucket_eos_create, at least that's how I was debugging it.

So unless I've missed something that situation should be fixed. Also it'd be nice to add if (!ctx->eos_sent) checks when eos buckets are sent.

Moreover there is this seemingly illogical piece of code:

if (ctx->eos_sent) {
e = apr_bucket_eos_create(f->c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(b, e);
return APR_SUCCESS;
}

why would you want to send EOS when the flag indicates that it has already been sent? I did a few tests and it seems that killing this code changes nothing. I could be wrong.

Thanks.

__________________________________________________________________
Stas Bekman JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/ mod_perl Guide ---> http://perl.apache.org
mailto:[EMAIL PROTECTED] http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org http://ticketmaster.com

Reply via email to