From: Sam Liddicott Date: Mon, 2 Feb 2009 12:12:07 +0000 (+0000) Subject: Make explicit free behave the same as implicit free X-Git-Url: http://git.samba.org/?p=metze%2Fsamba%2Fwip.git;a=commitdiff_plain;h=fc095dbedddf28ce32c711873317cf0b22579bfb Make explicit free behave the same as implicit free If a referenced allocation is explicitly freed the new owner should be the same as if the same allocation is implicitly freed (e.g. because it's owner was freed). Previously in talloc an explicit free will remove the top non-child reference but an implicit free will move the top (any) reference to be the new owner Signed-off-by: Sam Liddicott --- diff --git a/lib/talloc/testsuite.c b/lib/talloc/testsuite.c index 3d490ddf4931..c56cef40e0df 100644 --- a/lib/talloc/testsuite.c +++ b/lib/talloc/testsuite.c @@ -784,6 +784,71 @@ static bool test_unref_reparent(void) return true; } +/* If a referenced allocation is explicitly freed the new owner + should be the same as if the same allocation is implicitly freed + (because it's owner was freed). + Traditionally in talloc an explicit free will free the top non-child reference + but an implicit free will move the top (any) reference to be the new owner */ +static bool test_implicit_explicit_free(void) +{ + void *root, *p1, *p2, *p3, *ref, *r1; + int e, i; + + printf("test: test_implicit_explicit_free\n# SINGLE REFERENCE IMPLICIT FREE\n"); + + root = talloc_named_const(NULL, 0, "root"); + p1 = talloc_named_const(root, 1, "p1"); + p2 = talloc_named_const(p1, 1, "p2"); + /* Now root owns p1, and p1 owns p2 */ + + r1 = talloc_named_const(root, 1, "r1"); + ref = talloc_reference(r1, p2); + /* now r1 has ref reference to p2 */ + talloc_report_full(root, stderr); + + CHECK_BLOCKS(__FUNCTION__, p1, 2); + CHECK_BLOCKS(__FUNCTION__, p2, 1); + CHECK_BLOCKS(__FUNCTION__, r1, 2); + + fprintf(stderr, "Freeing p2\n"); + talloc_free(p2); + /* how many blocks is r1 taking against p2 ? */ + e=talloc_total_blocks(r1); + + talloc_report_full(root, stderr); + talloc_free(root); + + /* now repeat, but this time free p1 */ + printf("test: test_implicit_explicit_free\n# SINGLE REFERENCE EXPLICIT FREE\n"); + + root = talloc_named_const(NULL, 0, "root"); + p1 = talloc_named_const(root, 1, "p1"); + p2 = talloc_named_const(p1, 1, "p2"); + /* Now root owns p1, and p1 owns p2 */ + + r1 = talloc_named_const(root, 1, "r1"); + ref = talloc_reference(r1, p2); + /* now r1 has ref reference to p2 */ + talloc_report_full(NULL, stderr); + + CHECK_BLOCKS(__FUNCTION__, p1, 2); + CHECK_BLOCKS(__FUNCTION__, p2, 1); + CHECK_BLOCKS(__FUNCTION__, r1, 2); + + fprintf(stderr, "Freeing p1\n"); + talloc_free(p1); + /* how many blocks is r1 taking against p2 ? */ + i=talloc_total_blocks(r1); + talloc_report_full(NULL, stderr); + + CHECK_BLOCKS(__FUNCTION__,r1, e); + + talloc_free(root); + + printf("success: ref1\n"); + return true; +} + /* measure the speed of talloc versus malloc */ @@ -1132,6 +1197,7 @@ bool torture_local_talloc(struct torture_context *tctx) ret &= test_talloc_ptrtype(); ret &= test_talloc_free_in_destructor(); ret &= test_pool(); + ret &= test_implicit_explicit_free(); if (ret) { ret &= test_speed();