more fixes master4-talloc-sam
authorStefan Metzmacher <metze@samba.org>
Thu, 23 Jul 2009 11:43:46 +0000 (13:43 +0200)
committerStefan Metzmacher <metze@samba.org>
Thu, 23 Jul 2009 11:43:46 +0000 (13:43 +0200)
lib/talloc/talloc.c

index 6913c088516056da2df12df6d2d1b74e1800ab12..e28d91fc68c533223352e41ca4a0724245e6ebc8 100644 (file)
@@ -280,7 +280,8 @@ const char *talloc_parent_name(const void *ptr)
        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);
@@ -291,7 +292,13 @@ static inline void talloc_remove_from_parent(struct talloc_chunk *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;
+       }
 }
 
 /*
@@ -603,10 +610,6 @@ static inline int _talloc_free(void *ptr)
        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
@@ -656,7 +659,13 @@ static inline int _talloc_free(void *ptr)
                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);
 
@@ -721,9 +730,8 @@ void *_talloc_steal(const void *new_ctx, const void *ptr)
        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;
                }
@@ -736,7 +744,7 @@ void *_talloc_steal(const void *new_ctx, const void *ptr)
                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;