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

Reply via email to