svn commit: samba r15824 - in branches/SAMBA_4_0/source/lib/talloc: .

simo idra at samba.org
Tue May 23 12:23:23 GMT 2006


Tridge, can you backport this to trunk and SAMBA_3_0 ?

Simo.


On Tue, 2006-05-23 at 03:51 +0000, tridge at samba.org wrote:
> Author: tridge
> Date: 2006-05-23 03:51:44 +0000 (Tue, 23 May 2006)
> New Revision: 15824
> 
> WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=15824
> 
> Log:
> 
> fixed a subtle talloc bug to do with memory context loops. When you
> have a structure that references one of its parents, and a parent of
> that parent is freed, then the whole structure should be freed, not
> just the reference. 
> 
> this was found by the change notify code, as a side effect of fixing
> the memory leak yesterday
> 
> Modified:
>    branches/SAMBA_4_0/source/lib/talloc/talloc.c
>    branches/SAMBA_4_0/source/lib/talloc/talloc.h
>    branches/SAMBA_4_0/source/lib/talloc/testsuite.c
> 
> 
> Changeset:
> Modified: branches/SAMBA_4_0/source/lib/talloc/talloc.c
> ===================================================================
> --- branches/SAMBA_4_0/source/lib/talloc/talloc.c	2006-05-22 23:48:09 UTC (rev 15823)
> +++ branches/SAMBA_4_0/source/lib/talloc/talloc.c	2006-05-23 03:51:44 UTC (rev 15824)
> @@ -542,7 +542,13 @@
>  	tc = talloc_chunk_from_ptr(ptr);
>  
>  	if (tc->refs) {
> +		int is_child;
> +		struct talloc_reference_handle *handle = tc->refs;
> +		is_child = talloc_is_parent(handle, handle->ptr);
>  		talloc_reference_destructor(tc->refs);
> +		if (is_child) {
> +			return talloc_free(ptr);
> +		}
>  		return -1;
>  	}
>  
> @@ -1197,7 +1203,9 @@
>  			return TC_PTR_FROM_CHUNK(tc);
>  		}
>  		while (tc && tc->prev) tc = tc->prev;
> -		tc = tc->parent;
> +		if (tc) {
> +			tc = tc->parent;
> +		}
>  	}
>  	return NULL;
>  }
> @@ -1219,6 +1227,30 @@
>  	while (tc) {
>  		fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
>  		while (tc && tc->prev) tc = tc->prev;
> -		tc = tc->parent;
> +		if (tc) {
> +			tc = tc->parent;
> +		}
>  	}
>  }
> +
> +/*
> +  return 1 if ptr is a parent of context
> +*/
> +int talloc_is_parent(const void *context, const char *ptr)
> +{
> +	struct talloc_chunk *tc;
> +
> +	if (context == NULL) {
> +		return 0;
> +	}
> +
> +	tc = talloc_chunk_from_ptr(context);
> +	while (tc) {
> +		if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1;
> +		while (tc && tc->prev) tc = tc->prev;
> +		if (tc) {
> +			tc = tc->parent;
> +		}
> +	}
> +	return 0;
> +}
> 
> Modified: branches/SAMBA_4_0/source/lib/talloc/talloc.h
> ===================================================================
> --- branches/SAMBA_4_0/source/lib/talloc/talloc.h	2006-05-22 23:48:09 UTC (rev 15823)
> +++ branches/SAMBA_4_0/source/lib/talloc/talloc.h	2006-05-23 03:51:44 UTC (rev 15824)
> @@ -137,6 +137,7 @@
>  size_t talloc_get_size(const void *ctx);
>  void *talloc_find_parent_byname(const void *ctx, const char *name);
>  void talloc_show_parents(const void *context, FILE *file);
> +int talloc_is_parent(const void *context, const char *ptr);
>  
>  #endif
>  
> 
> Modified: branches/SAMBA_4_0/source/lib/talloc/testsuite.c
> ===================================================================
> --- branches/SAMBA_4_0/source/lib/talloc/testsuite.c	2006-05-22 23:48:09 UTC (rev 15823)
> +++ branches/SAMBA_4_0/source/lib/talloc/testsuite.c	2006-05-23 03:51:44 UTC (rev 15824)
> @@ -824,7 +824,7 @@
>  }
>  
> 
> -BOOL test_lifeless(void)
> +static BOOL test_lifeless(void)
>  {
>  	char *top = talloc_new(NULL);
>  	char *parent, *child; 
> @@ -836,14 +836,57 @@
>  	child = talloc_strdup(parent, "child");  
>  	talloc_reference(child, parent);
>  	talloc_reference(child_owner, child); 
> +	talloc_report_full(top, stdout);
>  	talloc_unlink(top, parent);
>  	talloc_free(child);
>  	talloc_report_full(top, stdout);
>  	talloc_free(top);
> +	talloc_free(child_owner);
> +#if 0
> +	talloc_free(child);
> +#endif
>  	return True;
>  }
>  
> +static int loop_destructor_count;
>  
> +static int test_loop_destructor(void *ptr)
> +{
> +	printf("loop destructor\n");
> +	loop_destructor_count++;
> +	return 0;
> +}
> +
> +static BOOL test_loop(void)
> +{
> +	char *top = talloc_new(NULL);
> +	char *parent;
> +	struct req1 {
> +		char *req2, *req3;
> +	} *req1;
> +
> +	printf("TESTING TALLOC LOOP DESTRUCTION\n");
> +	parent = talloc_strdup(top, "parent");
> +	req1 = talloc(parent, struct req1);
> +	req1->req2 = talloc_strdup(req1, "req2");  
> +	talloc_set_destructor(req1->req2, test_loop_destructor);
> +	req1->req3 = talloc_strdup(req1, "req3");
> +	talloc_reference(req1->req3, req1);
> +	talloc_report_full(top, stdout);
> +	talloc_free(parent);
> +	talloc_report_full(top, stdout);
> +	talloc_report_full(NULL, stdout);
> +	talloc_free(top);
> +
> +	if (loop_destructor_count != 1) {
> +		printf("FAILED TO FIRE LOOP DESTRUCTOR\n");
> +		return False;
> +	}
> +
> +	return True;
> +}
> +
> +
>  BOOL torture_local_talloc(struct torture_context *torture) 
>  {
>  	BOOL ret = True;
> @@ -861,6 +904,7 @@
>  	ret &= test_realloc_fn();
>  	ret &= test_type();
>  	ret &= test_lifeless();
> +	ret &= test_loop();
>  	if (ret) {
>  		ret &= test_speed();
>  	}
-- 
Simo Sorce
Samba Team GPL Compliance Officer
email: idra at samba.org
http://samba.org



More information about the samba-cvs mailing list