apr-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Rici Lake <r...@ricilake.net>
Subject Re: Pool buckets, transient buckets and bucket_setaside
Date Tue, 26 Apr 2005 01:14:58 GMT

On 25-Apr-05, at 6:48 PM, Cliff Woolley wrote:

> On Mon, 25 Apr 2005, Rici Lake wrote:
>
>> Surely this is equally true of any pool-related resource. For example,
>> a file which has been opened and has a pool cleanup registered would
>> have exactly the same lifetime as a pool-allocated string.
>
> Hmm... for some reason I thought file buckets morphed themselves upon 
> pool
> cleanup, too.  That they don't could be viewed as a bug in file 
> buckets.

Indeed it could. Or it could demonstrate that auto-setaside is 
unnecessary.

Let me try another response to this:

> They set themselves aside when the pool in which their data was 
> allocated
> is in the process of being destroyed.  This is necessary because no 
> other
> bucket type has a similarly unpredictable lifetime.  Even transient
> buckets have a lifetime that is well-known: they last until the call 
> chain
> returns.  Pool buckets might not even live that long.  Don't think 
> just in
> terms of httpd's usage of buckets here -- this is an APR construct.

OK, but that's not going to work either:

apr_status_t accept_brigade(context_t *ctx, apr_bucket_brigade *bb)
{
     while (!APR_BRIGADE_EMPTY(bb)) {
         const char *data;
         apr_size_t len;
         apr_bucket *e = APR_BRIGADE_FIRST(bb);
         apr_status_t result = apr_bucket_read(e, &data, &len, 1);
         if (result != APR_SUCCESS) return result;
         else {
             apr_size_t i;
             for (i = 0; i < len; ++i) {
                 rv = handle_char(ctx, data[i]);
                 /* OJO! */
             }
         }
     }
}

So, we're at the comment OJO! e is an automorphing bucket, say a pool 
bucket. Something in handle_char triggers the termination of e's data. 
The automorphing cleanup functions jumps in and fixes it. But buf is 
pointing into limbo.

This would only not be a problem if apr_bucket_read() froze the data. 
But that would defeat the whole point of lazy automorphing. (On the 
other hand, it is exactly what would happen with an automorphed file 
bucket, if there were such a thing. So it actually would be feasible in 
that case -- but not with pool buckets.)

When a put a bucket into a brigade, I'm making an implicit contract 
that the bucket's data will be valid at any time that the brigade is 
valid. Automorphing is not enough to ensure that, in the face of 
buckets whose data might become invalid at any time. So if I'm allowed 
to put a bucket into a brigade knowing that the bucket's lifespan is 
shorter than the effective lifespan of the brigade, I've also got to 
negotiate with the consumer so that they know when they can and cannot 
rely on a previously apr_bucket_read() pointer. I don't know how to 
write that contract, and I'm skeptical that it can be written.

If you accept that, then automorphing doesn't deal with the case where 
the lifespan of the data is shorter than that of the brigade, and it 
isn't necessary in the case where the lifespan is longer than that of 
the brigade, since I'm required to call apr_bucket_setaside if I'm 
going to keep a bucket around.

In fact, automorphing a bucket after it has been moved could suffer the 
same bug as the above example, but it's unlikely since the event which 
would trigger the automorph is not going to be within the call to 
accept_brigade(). Probably.


Mime
View raw message