diff options
author | Jeremy Allison <jra@samba.org> | 2015-03-03 17:02:47 -0800 |
---|---|---|
committer | Karolin Seeger <kseeger@samba.org> | 2015-03-15 22:14:08 +0100 |
commit | 1b584cf8aa420844216033f4f43ca16fd53eb0fe (patch) | |
tree | 050fddd730b21626ac69770b3767700dec700599 | |
parent | 8194d069e55914710656abc8fb9d16a1fb24eb1c (diff) | |
download | samba-1b584cf8aa420844216033f4f43ca16fd53eb0fe.tar.gz |
lib: talloc: Allow destructors to reparent the object they're called on.
If a destructor returns failure (-1) when freeing a child, talloc
must then reparent the child.
Firstly it tries the owner of any reference, next the parent of the
current object calling _talloc_free_children_internal(), and finally
the null context in the last resort.
If a destructor reparented its own object, which can be a very
desirable thing to do (a destructor can make a decision it isn't
time to die yet, and as the parent may be going away it might
want to move itself to longer-term storage) then this new parent
gets overwritten by the existing reparenting logic.
This patch checks when freeing a child if it already reparented
itself, and if it did doesn't then overwrite the new parent.
Makes destructors more flexible.
Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ira Cooper <ira@samba.org>
(cherry picked from commit cc4e5481ea060db7f6d8a83619d859b2e002eb90)
-rw-r--r-- | lib/talloc/talloc.c | 7 |
1 files changed, 7 insertions, 0 deletions
diff --git a/lib/talloc/talloc.c b/lib/talloc/talloc.c index 1ccb039ff74..46f10f4697c 100644 --- a/lib/talloc/talloc.c +++ b/lib/talloc/talloc.c @@ -1470,6 +1470,13 @@ static inline void _talloc_free_children_internal(struct talloc_chunk *tc, if (p) new_parent = TC_PTR_FROM_CHUNK(p); } if (unlikely(_talloc_free_internal(child, location) == -1)) { + if (talloc_parent_chunk(child) != tc) { + /* + * Destructor already reparented this child. + * No further reparenting needed. + */ + return; + } if (new_parent == null_context) { struct talloc_chunk *p = talloc_parent_chunk(ptr); if (p) new_parent = TC_PTR_FROM_CHUNK(p); |