From 3289a5d84f73bf044e5767a6c47a3f7bf8357c08 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 5 Mar 2015 12:48:47 -0800 Subject: [PATCH 1/5] lib: talloc: Fix bug when calling a destructor. If the destructor itself calls talloc_set_destructor() and returns -1, the new destructor set is overwritten by talloc. Dectect that and leave the new destructor in place. Needed for bug: https://bugzilla.samba.org/show_bug.cgi?id=11144 Signed-off-by: Jeremy Allison Reviewed-by: Ira Cooper --- lib/talloc/talloc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/talloc/talloc.c b/lib/talloc/talloc.c index fa56ea5..1ccb039 100644 --- a/lib/talloc/talloc.c +++ b/lib/talloc/talloc.c @@ -991,7 +991,13 @@ static inline int _talloc_free_internal(void *ptr, const char *location) } tc->destructor = (talloc_destructor_t)-1; if (d(ptr) == -1) { - tc->destructor = d; + /* + * Only replace the destructor pointer if + * calling the destructor didn't modify it. + */ + if (tc->destructor == (talloc_destructor_t)-1) { + tc->destructor = d; + } return -1; } tc->destructor = NULL; -- 2.2.0.rc0.207.ga3a616c From cc4e5481ea060db7f6d8a83619d859b2e002eb90 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 3 Mar 2015 17:02:47 -0800 Subject: [PATCH 2/5] 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. Needed for bug: https://bugzilla.samba.org/show_bug.cgi?id=11144 Signed-off-by: Jeremy Allison Reviewed-by: Volker Lendecke Reviewed-by: Ira Cooper --- lib/talloc/talloc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/talloc/talloc.c b/lib/talloc/talloc.c index 1ccb039..46f10f4 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); -- 2.2.0.rc0.207.ga3a616c From 6b0cecee1b864a0589836caf9f5f2892f8cb6926 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 3 Mar 2015 17:12:32 -0800 Subject: [PATCH 3/5] lib: talloc: Test suite for the new destructor reparent logic. Signed-off-by: Jeremy Allison Reviewed-by: Volker Lendecke Reviewed-by: Ira Cooper Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Sun Mar 8 20:52:43 CET 2015 on sn-devel-104 --- lib/talloc/testsuite.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/lib/talloc/testsuite.c b/lib/talloc/testsuite.c index a878278..eb3e13d 100644 --- a/lib/talloc/testsuite.c +++ b/lib/talloc/testsuite.c @@ -981,6 +981,84 @@ static bool test_free_parent_deny_child(void) return true; } +struct new_parent { + void *new_parent; + char val[20]; +}; + +static int reparenting_destructor(struct new_parent *np) +{ + talloc_set_destructor(np, NULL); + (void)talloc_move(np->new_parent, &np); + return -1; +} + +static bool test_free_parent_reparent_child(void) +{ + void *top = talloc_new(NULL); + char *level1; + char *alternate_level1; + char *level2; + struct new_parent *level3; + + printf("test: free_parent_reparent_child\n# " + "TALLOC FREE PARENT REPARENT CHILD\n"); + + level1 = talloc_strdup(top, "level1"); + alternate_level1 = talloc_strdup(top, "alternate_level1"); + level2 = talloc_strdup(level1, "level2"); + level3 = talloc(level2, struct new_parent); + level3->new_parent = alternate_level1; + memset(level3->val, 'x', sizeof(level3->val)); + + talloc_set_destructor(level3, reparenting_destructor); + talloc_free(level1); + + CHECK_PARENT("free_parent_reparent_child", + level3, alternate_level1); + + talloc_free(top); + + printf("success: free_parent_reparent_child\n"); + return true; +} + +static bool test_free_parent_reparent_child_in_pool(void) +{ + void *top = talloc_new(NULL); + char *level1; + char *alternate_level1; + char *level2; + void *pool; + struct new_parent *level3; + + printf("test: free_parent_reparent_child_in_pool\n# " + "TALLOC FREE PARENT REPARENT CHILD IN POOL\n"); + + pool = talloc_pool(top, 1024); + level1 = talloc_strdup(pool, "level1"); + alternate_level1 = talloc_strdup(top, "alternate_level1"); + level2 = talloc_strdup(level1, "level2"); + level3 = talloc(level2, struct new_parent); + level3->new_parent = alternate_level1; + memset(level3->val, 'x', sizeof(level3->val)); + + talloc_set_destructor(level3, reparenting_destructor); + talloc_free(level1); + talloc_set_destructor(level3, NULL); + + CHECK_PARENT("free_parent_reparent_child_in_pool", + level3, alternate_level1); + + /* Even freeing alternate_level1 should leave pool alone. */ + talloc_free(alternate_level1); + talloc_free(top); + + printf("success: free_parent_reparent_child_in_pool\n"); + return true; +} + + static bool test_talloc_ptrtype(void) { void *top = talloc_new(NULL); @@ -1674,6 +1752,10 @@ bool torture_local_talloc(struct torture_context *tctx) test_reset(); ret &= test_free_parent_deny_child(); test_reset(); + ret &= test_free_parent_reparent_child(); + test_reset(); + ret &= test_free_parent_reparent_child_in_pool(); + test_reset(); ret &= test_talloc_ptrtype(); test_reset(); ret &= test_talloc_free_in_destructor(); -- 2.2.0.rc0.207.ga3a616c From 3929abfc6b5a3ae8a27da57d4dbee9524e3585e3 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 27 Jan 2015 13:07:34 +0100 Subject: [PATCH 4/5] talloc: fix _talloc_total_limit_size prototype Signed-off-by: Stefan Metzmacher Reviewed-by: Ralph Boehme --- lib/talloc/talloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/talloc/talloc.c b/lib/talloc/talloc.c index 46f10f4..c10fd53 100644 --- a/lib/talloc/talloc.c +++ b/lib/talloc/talloc.c @@ -1064,7 +1064,7 @@ static inline int _talloc_free_internal(void *ptr, const char *location) return 0; } -static size_t _talloc_total_limit_size(const void *ptr, +static inline size_t _talloc_total_limit_size(const void *ptr, struct talloc_memlimit *old_limit, struct talloc_memlimit *new_limit); -- 2.2.0.rc0.207.ga3a616c From 7bef5e4f0e5ff4a4187f3d63e51a1725ff32b771 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 9 Mar 2015 09:07:24 +0100 Subject: [PATCH 5/5] talloc: version 2.1.2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes: - Allow destructors to reparent the object - Allow destructors to remove itself - Build improvements Signed-off-by: Stefan Metzmacher Reviewed-by: Günther Deschner --- lib/talloc/ABI/pytalloc-util-2.1.2.sigs | 6 ++++ lib/talloc/ABI/talloc-2.1.2.sigs | 64 +++++++++++++++++++++++++++++++++ lib/talloc/wscript | 2 +- 3 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 lib/talloc/ABI/pytalloc-util-2.1.2.sigs create mode 100644 lib/talloc/ABI/talloc-2.1.2.sigs diff --git a/lib/talloc/ABI/pytalloc-util-2.1.2.sigs b/lib/talloc/ABI/pytalloc-util-2.1.2.sigs new file mode 100644 index 0000000..961c1a8 --- /dev/null +++ b/lib/talloc/ABI/pytalloc-util-2.1.2.sigs @@ -0,0 +1,6 @@ +pytalloc_CObject_FromTallocPtr: PyObject *(void *) +pytalloc_Check: int (PyObject *) +pytalloc_GetObjectType: PyTypeObject *(void) +pytalloc_reference_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *) +pytalloc_steal: PyObject *(PyTypeObject *, void *) +pytalloc_steal_ex: PyObject *(PyTypeObject *, TALLOC_CTX *, void *) diff --git a/lib/talloc/ABI/talloc-2.1.2.sigs b/lib/talloc/ABI/talloc-2.1.2.sigs new file mode 100644 index 0000000..eae12cc --- /dev/null +++ b/lib/talloc/ABI/talloc-2.1.2.sigs @@ -0,0 +1,64 @@ +_talloc: void *(const void *, size_t) +_talloc_array: void *(const void *, size_t, unsigned int, const char *) +_talloc_free: int (void *, const char *) +_talloc_get_type_abort: void *(const void *, const char *, const char *) +_talloc_memdup: void *(const void *, const void *, size_t, const char *) +_talloc_move: void *(const void *, const void *) +_talloc_pooled_object: void *(const void *, size_t, const char *, unsigned int, size_t) +_talloc_realloc: void *(const void *, void *, size_t, const char *) +_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *) +_talloc_reference_loc: void *(const void *, const void *, const char *) +_talloc_set_destructor: void (const void *, int (*)(void *)) +_talloc_steal_loc: void *(const void *, const void *, const char *) +_talloc_zero: void *(const void *, size_t, const char *) +_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *) +talloc_asprintf: char *(const void *, const char *, ...) +talloc_asprintf_append: char *(char *, const char *, ...) +talloc_asprintf_append_buffer: char *(char *, const char *, ...) +talloc_autofree_context: void *(void) +talloc_check_name: void *(const void *, const char *) +talloc_disable_null_tracking: void (void) +talloc_enable_leak_report: void (void) +talloc_enable_leak_report_full: void (void) +talloc_enable_null_tracking: void (void) +talloc_enable_null_tracking_no_autofree: void (void) +talloc_find_parent_byname: void *(const void *, const char *) +talloc_free_children: void (void *) +talloc_get_name: const char *(const void *) +talloc_get_size: size_t (const void *) +talloc_increase_ref_count: int (const void *) +talloc_init: void *(const char *, ...) +talloc_is_parent: int (const void *, const void *) +talloc_named: void *(const void *, size_t, const char *, ...) +talloc_named_const: void *(const void *, size_t, const char *) +talloc_parent: void *(const void *) +talloc_parent_name: const char *(const void *) +talloc_pool: void *(const void *, size_t) +talloc_realloc_fn: void *(const void *, void *, size_t) +talloc_reference_count: size_t (const void *) +talloc_reparent: void *(const void *, const void *, const void *) +talloc_report: void (const void *, FILE *) +talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *) +talloc_report_depth_file: void (const void *, int, int, FILE *) +talloc_report_full: void (const void *, FILE *) +talloc_set_abort_fn: void (void (*)(const char *)) +talloc_set_log_fn: void (void (*)(const char *)) +talloc_set_log_stderr: void (void) +talloc_set_memlimit: int (const void *, size_t) +talloc_set_name: const char *(const void *, const char *, ...) +talloc_set_name_const: void (const void *, const char *) +talloc_show_parents: void (const void *, FILE *) +talloc_strdup: char *(const void *, const char *) +talloc_strdup_append: char *(char *, const char *) +talloc_strdup_append_buffer: char *(char *, const char *) +talloc_strndup: char *(const void *, const char *, size_t) +talloc_strndup_append: char *(char *, const char *, size_t) +talloc_strndup_append_buffer: char *(char *, const char *, size_t) +talloc_total_blocks: size_t (const void *) +talloc_total_size: size_t (const void *) +talloc_unlink: int (const void *, void *) +talloc_vasprintf: char *(const void *, const char *, va_list) +talloc_vasprintf_append: char *(char *, const char *, va_list) +talloc_vasprintf_append_buffer: char *(char *, const char *, va_list) +talloc_version_major: int (void) +talloc_version_minor: int (void) diff --git a/lib/talloc/wscript b/lib/talloc/wscript index 986492c..97c52c3 100644 --- a/lib/talloc/wscript +++ b/lib/talloc/wscript @@ -1,7 +1,7 @@ #!/usr/bin/env python APPNAME = 'talloc' -VERSION = '2.1.1' +VERSION = '2.1.2' blddir = 'bin' -- 2.2.0.rc0.207.ga3a616c