[ccan] RFC: draft rfc822 module

Rusty Russell rusty at rustcorp.com.au
Tue May 22 14:05:14 EST 2012


On Mon, 21 May 2012 05:59:31 -0500, Jonathan Nieder <jrnieder at gmail.com> wrote:
> David Gibson wrote:
> > On Sun, May 20, 2012 at 09:38:09PM -0500, Jonathan Nieder wrote:
> >> David Gibson wrote:
> 
> >>> --- /dev/null
> >>> +++ b/ccan/rfc822/test/run-allocation-failure.c
> >>> @@ -0,0 +1,56 @@
> >> [...]
> >>> +	talloc_set_allocator(failing_malloc, free, realloc);
> >>
> >> By the way, as an alternative to the rfc822 allocation failure
> >> callback, I can set up exit-cleanly-on-failed-allocation semantics
> >> here.  I can even use talloc_add_external to make my handler's
> >> behavior depend on the talloc context.
> >
> > Um.. I'm not sure what you mean by this.
> 
> Sorry, thinko on my part.
> 
> What I meant is that a caller who wants to exit(1) instead of abort()
> for allocation failures can make talloc take care of that, using
> talloc_set_allocator() or talloc_add_external().
> 
> The thinko was that if the caller wants to suppress the abort() but
> does not want to exit, this trick isn't enough.  It can't replace the
> functionality of the rfc822 failed allocation handler completely.
> 
> Drat, error handling is _hard_.

Yes, and experience shows that no one handles OOM correctly, so spending
effort on it is dubious.

One thought:

It's tempting to expose 'struct rfc822' in the header, and let the
caller allocate and free it (ie. provide rfc822_init() and
rfc822_cleanup()).  I'm moving to this pattern, because a fair few CCAN
users are interested int tiny systems (and thus resent malloc usage).

Less of an advantage for you, since you allocate internally.  But you
could then provide a global hook for alloc/resize/free which hands the
msg.  Talloc users can easily make this a wrapper (or that could be the
default).  If you end up using complex allocations internally, then you
might want to insist that it be talloc.

Error handling could be done here:

        static void *myalloc(struct rfc822 *msg, size_t len)
        {
                void *ret = talloc(msg, len);
                if (!ret) {
                        struct myrfc822 *mymsg = (struct myrfc822 *)msg;
                        mymsg->alloc_failed++;
                }
                return ret;
        }

Just a thought,
Rusty.


More information about the ccan mailing list