[QUICK] talloc bugs

Rusty Russell rusty at rustcorp.com.au
Wed Jul 1 12:24:24 GMT 2009


On Wed, 1 Jul 2009 09:28:32 pm simo wrote:
> On Wed, 2009-07-01 at 21:20 +0930, Rusty Russell wrote:
> > I don't think references are a fundamental part of talloc: they are
> > useful, and I think helpers to allow them could be great, but I'd rather
> > see some explicit demarcation of what is reference counted.  See followup
> > code.
>
> Another way could be to attach some code like we do with
> talloc_destructor(), with the ability to tell the calling talloc code to
> reparent instead of free.

This would work, and doesn't even need to be inside talloc (tho if you want to
support talloc_realloc it should be: references currently don't allow that).

Cheers,
Rusty.

#ifndef TALLOC_LINK_H
#define TALLOC_LINK_H

/* Add a link between a context and another talloc object.  This
 * implicitly does a steal of the linked object to become a descendent
 * of ctx.
 *
 * You can do any number of talloc_link() calls to a linked object.
 * talloc_steal or talloc_free of the linked object breaks the links
 * (you probably don't want to do this).  Otherwise, freeing the last
 * talloc_linked ctx frees linked.
 */
int talloc_link(const void *ctx, const void *linked);

/* Explicitly remove a link: normally it is implied by freeing the
 * ctx.  ctx must have been linked to the object using talloc_link.
 * Removing the last link frees the object. */
void talloc_delink(const void *ctx, const void *linked);

#endif /* TALLOC_LINK_H */

#include <ccan/talloc/talloc.h>
#include <ccan/talloc_link/talloc_link.h>

struct talloc_link {
	struct talloc_link *next, *prev;
	const void *obj;
};

static int destroy_link(struct talloc_link *link)
{
	/* Try to hand off parentage to another link. */
	if (talloc_is_parent(link, link->obj))
		talloc_steal(link->next, link->obj);

	/* Unlink ourselves */
	link->next->prev = link->prev;
	link->prev->next = link->next;
	return 0;
}

int talloc_link(const void *ctx, const void *linked)
{
	struct talloc_link *link, *oldlink;

	link = talloc(ctx, struct talloc_link);
	if (!link)
		return -1;

	talloc_set_destructor(link, destroy_link);

	/* Already linked? */
	oldlink = talloc_get_type(talloc_parent(linked), struct talloc_link);
	if (oldlink) {
		link->next = oldlink;
		link->prev = oldlink->prev;
		oldlink->prev = link;
		link->prev->next = link;
	} else {
		link->next = link->prev = link;
	}
	link->obj = talloc_steal(link, linked);
	return 0;
}

void talloc_delink(const void *ctx, const void *linked)
{
	struct link *link, *i;

	link = talloc_get_type(talloc_parent(linked), struct talloc_link);
	/* Talloc steal could have taken us away. */
	if (!link)
		return;
	
	i = link;
	do {
		if (talloc_is_parent(ctx, i)) {
			talloc_free(i);
			return;
		}
		i = i->next;
	} while (i != link);

	/* Talloc steal then linked to by other links? */
}




More information about the samba-technical mailing list