Joachim Zobel wrote:
> Am Dienstag, den 02.01.2007, 01:14 -0800 schrieb Drew Bertola:
>
>> line 91 looks like this:
>>
>> apr_bucket_read(e, &str, &len, APR_NONBLOCK_READ);
>>
>> Also, it only happens if I use
>>
>> APR_BRIGADE_INSERT_TAIL(ctx->bb, e);
>>
>
> Ah, understood.
>
> You don't mention this, but you probably have a
>
> for ( e = APR_BRIGADE_FIRST(bb) ;
> e != APR_BRIGADE_SENTINEL(bb) ;
> e = APR_BUCKET_NEXT(e) ) {
>
> for your loop. Right?
>
> So if you _move_ e to another brigade, the e != APR_BRIGADE_SENTINEL(bb)
> will never be fullfilled and APR_BUCKET_NEXT(e) will step through the
> wrong brigade and will treat the sentinel as a bucket. This causes the
> observed segfault.
Are you sure about that?
Again, makes me wish for a null output filter example.
My understanding is that it would need this:
- create context if it doesn't already exist.
- loop through buckets (from FIRST to SENTINEL) in brigade passed to
filter appending each bucket to my context's brigade.
- pass my brigade to next filter.
So, shouldn't this work? ...
static int null_filter(ap_filter_t *f, apr_bucket_brigade *bb)
{
null_filter_struct *ctx = f->ctx;
apr_bucket *e;
/*
* if we don't have a context for this filter, let's create one and
* create it's bucket brigade.
*/
if ( ! ctx )
{
f->ctx = ctx = apr_pcalloc(f->r->pool, sizeof(*ctx));
ctx->bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
}
/*
* let's loop through the buckets passed to us.
*/
for( e = APR_BRIGADE_FIRST(bb);
e != APR_BRIGADE_SENTINEL(bb);
e = APR_BUCKET_NEXT(e) )
{
/*
* if the bucket is an end of stream bucket or a flush bucket,
* we can pass on what we have so far and be done with this brigade.
*/
if ( APR_BUCKET_IS_EOS(e) || APR_BUCKET_IS_FLUSH(e) )
{
APR_BRIGADE_INSERT_TAIL(ctx->bb, e);
APR_BUCKET_REMOVE(e);
ap_pass_brigade(f->next, ctx->bb);
return APR_SUCCESS;
}
APR_BRIGADE_INSERT_TAIL(ctx->bb, e);
APR_BUCKET_REMOVE(e);
}
ap_pass_brigade(f->next, ctx->bb);
return APR_SUCCESS;
}
I'm not sure about these things:
- do I need to look out for APR_BUCKET_IS_EOS or APR_BUCKET_IS_FLUSH or
are they implicit before APR_BRIGADE_IS_SENTINEL?
- do I need to use ap_pass_brigade()? I've used it here before returning.
--
Drew