On 15 Mar 2016, at 1:09 PM, Yann Ylavic <ylavic....@gmail.com> wrote:

>> I just gave it a try and it was a lot more elegant than I thought.
>> 
>> You create an array the precise size you need, and off you go.
> 
> That's indeed elegant enough, but I think I prefer the plain array
> solution, still :p
> 
> Don't you like?
> {
>    apr_pollfd_t pfds[3];
>    /* or */
>    apr_pollfd_t *pfds = apr_pcalloc(p, 3 * apr_pollfd_t);
> 
>    pfds[0].desc_type = APR_POLL_SOCKET;
>    pfds[0].desc.s = s0;
>    ...
>    pfds[1].desc_type = APR_POLL_SOCKET;
>    pfds[1].desc.s = s1;
>    ...
>    pfds[2].desc_type = APR_NO_DESC;
> 
>    ap_mpm_register_poll_callback_timeout(pfds, pool, ...);
> }

The trouble with the above is that because of the pool cleanup we now have, 
pfds[3] needs to live as long as pool p. In your example it does, but there is 
nothing stopping someone trying to allocate pfds[3] on the stack and then 
returning. Later the cleanup is run, and boom - difficult to debug crash or 
weird behaviour.

With the array you’re guaranteed the memory is allocated from a pool, which 
means the pool cleanup will always be safe.

What we should also do is drop the apr_pool_t *p parameter and read it from 
apr_header_array_t’s pool instead. This will be a further check to stop the 
caller from doing anything pathological, as we definitely know the cleanup and 
the array belong to each other, and our API becomes simpler still.

Attached patch does this.

Regards,
Graham
—

Attachment: httpd-register-poll3.patch
Description: Binary data

Reply via email to