return tc? tc->name : NULL;
}
-static inline void talloc_remove_from_parent(struct talloc_chunk *tc)
+static inline void talloc_remove_from_parent(struct talloc_chunk *tc,
+ bool reset_parent)
{
if (!TALLOC_INVALID_PARENT(tc)) {
_TLIST_REMOVE(tc->parent->child, tc);
if (tc->prev) tc->prev->next = tc->next;
if (tc->next) tc->next->prev = tc->prev;
}
-// tc->parent = tc->prec = tc->next = NULL;
+ tc->prev = tc->next = NULL;
+ /*
+ * Note: we only reset tc->parent = NULL when the caller asked for it
+ */
+ if (reset_parent) {
+ tc->parent = NULL;
+ }
}
/*
tc = talloc_chunk_from_ptr(ptr);
if (unlikely(tc->refs)) {
- /*TODO: Fix this loop detection. The code here breaks top reference if
- it is also one of our children. It is insufficient and can lead
- to dangling references */
-
int is_child;
/* check this is a reference from a child or grantchild
* back to it's parent or grantparent
tc->destructor = NULL;
}
- talloc_remove_from_parent(tc);
+ /*
+ * Note: we ask talloc_remove_from_parent() to keep
+ * tc->parent valid, because _talloc_free_children()
+ * needs it to find the parent for child where
+ * the destructor rejects the _talloc_free()
+ */
+ talloc_remove_from_parent(tc, false);
_talloc_free_children(tc);
tc = talloc_chunk_from_ptr(ptr);
if (unlikely(new_ctx == NULL)) {
- talloc_remove_from_parent(tc);
+ talloc_remove_from_parent(tc, true);
- tc->parent = tc->next = tc->prev = NULL;
if (unlikely(no_owner_null)) {
tc->parent = TALLOC_MAGIC_NO_OWNER_TC;
}
return discard_const_p(void, ptr);
}
- talloc_remove_from_parent(tc);
+ talloc_remove_from_parent(tc, true);
tc->parent = new_tc;
if (new_tc->child) new_tc->child->parent = NULL;