From 9c8a9d0ac4cb062e8de25a5dbaed823e597a128f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 29 Aug 2006 16:54:12 +0000 Subject: r17922: sync samba3's talloc with samba4's and move the samba3 specific stuff to tallocmsg.c metze (This used to be commit 7704e3e51dec1768772663024a0579cb4a271cc1) --- source3/include/talloc.h | 91 +++++++----- source3/lib/talloc.c | 356 +++++++++++++++++++++-------------------------- source3/lib/tallocmsg.c | 49 ++++++- source3/lib/util.c | 2 +- 4 files changed, 261 insertions(+), 237 deletions(-) (limited to 'source3') diff --git a/source3/include/talloc.h b/source3/include/talloc.h index db88ce6ed5..fdc0fd3494 100644 --- a/source3/include/talloc.h +++ b/source3/include/talloc.h @@ -5,6 +5,7 @@ Samba temporary memory allocation functions Copyright (C) Andrew Tridgell 2004-2005 + Copyright (C) Stefan Metzmacher 2006 ** NOTE! The following LGPL license applies to the talloc ** library. This does NOT imply that all of Samba is released @@ -40,9 +41,43 @@ typedef void TALLOC_CTX; #define TALLOC_DEPRECATED 0 #endif +#ifndef PRINTF_ATTRIBUTE +#if (__GNUC__ >= 3) +/** Use gcc attribute to check printf fns. a1 is the 1-based index of + * the parameter containing the format, and a2 the index of the first + * argument. Note that some gcc 2.x versions don't handle this + * properly **/ +#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) +#else +#define PRINTF_ATTRIBUTE(a1, a2) +#endif +#endif + +/* try to make talloc_set_destructor() and talloc_steal() type safe, + if we have a recent gcc */ +#if (__GNUC__ >= 3) +#define _TALLOC_TYPEOF(ptr) __typeof__(ptr) +#define talloc_set_destructor(ptr, function) \ + do { \ + int (*_talloc_destructor_fn)(_TALLOC_TYPEOF(ptr)) = (function); \ + _talloc_set_destructor((ptr), (int (*)(void *))_talloc_destructor_fn); \ + } while(0) +/* this extremely strange macro is to avoid some braindamaged warning + stupidity in gcc 4.1.x */ +#define talloc_steal(ctx, ptr) ({ _TALLOC_TYPEOF(ptr) __talloc_steal_ret = (_TALLOC_TYPEOF(ptr))_talloc_steal((ctx),(ptr)); __talloc_steal_ret; }) +#define talloc_reference(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_reference((ctx),(ptr)) +#else +#define talloc_set_destructor(ptr, function) \ + _talloc_set_destructor((ptr), (int (*)(void *))(function)) +#define _TALLOC_TYPEOF(ptr) void * +#define talloc_steal(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_steal((ctx),(ptr)) +#define talloc_reference(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_reference((ctx),(ptr)) +#endif + /* useful macros for creating type checked pointers */ #define talloc(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type) #define talloc_size(ctx, size) talloc_named_const(ctx, size, __location__) +#define talloc_ptrtype(ctx, ptr) (_TALLOC_TYPEOF(ptr))talloc_size(ctx, sizeof(*(ptr))) #define talloc_new(ctx) talloc_named_const(ctx, 0, "talloc_new: " __location__) @@ -52,29 +87,18 @@ typedef void TALLOC_CTX; #define talloc_zero_array(ctx, type, count) (type *)_talloc_zero_array(ctx, sizeof(type), count, #type) #define talloc_array(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, #type) #define talloc_array_size(ctx, size, count) _talloc_array(ctx, size, count, __location__) +#define talloc_array_ptrtype(ctx, ptr, count) (_TALLOC_TYPEOF(ptr))talloc_array_size(ctx, sizeof(*(ptr)), count) #define talloc_realloc(ctx, p, type, count) (type *)_talloc_realloc_array(ctx, p, sizeof(type), count, #type) #define talloc_realloc_size(ctx, ptr, size) _talloc_realloc(ctx, ptr, size, __location__) #define talloc_memdup(t, p, size) _talloc_memdup(t, p, size, __location__) -#define malloc_p(type) (type *)malloc(sizeof(type)) -#define malloc_array_p(type, count) (type *)realloc_array(NULL, sizeof(type), count) -#define realloc_p(p, type, count) (type *)realloc_array(p, sizeof(type), count) - -#if 0 -/* Not correct for Samba3. */ -#define data_blob(ptr, size) data_blob_named(ptr, size, "DATA_BLOB: "__location__) -#define data_blob_talloc(ctx, ptr, size) data_blob_talloc_named(ctx, ptr, size, "DATA_BLOB: "__location__) -#define data_blob_dup_talloc(ctx, blob) data_blob_talloc_named(ctx, (blob)->data, (blob)->length, "DATA_BLOB: "__location__) -#endif - #define talloc_set_type(ptr, type) talloc_set_name_const(ptr, #type) #define talloc_get_type(ptr, type) (type *)talloc_check_name(ptr, #type) #define talloc_find_parent_bytype(ptr, type) (type *)talloc_find_parent_byname(ptr, #type) - #if TALLOC_DEPRECATED #define talloc_zero_p(ctx, type) talloc_zero(ctx, type) #define talloc_p(ctx, type) talloc(ctx, type) @@ -83,43 +107,39 @@ typedef void TALLOC_CTX; #define talloc_destroy(ctx) talloc_free(ctx) #endif -#ifndef PRINTF_ATTRIBUTE -#if (__GNUC__ >= 3) -/** Use gcc attribute to check printf fns. a1 is the 1-based index of - * the parameter containing the format, and a2 the index of the first - * argument. Note that some gcc 2.x versions don't handle this - * properly **/ -#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) -#else -#define PRINTF_ATTRIBUTE(a1, a2) -#endif -#endif - - /* The following definitions come from talloc.c */ void *_talloc(const void *context, size_t size); -void talloc_set_destructor(const void *ptr, int (*destructor)(void *)); -void talloc_increase_ref_count(const void *ptr); -void *talloc_reference(const void *context, const void *ptr); +void _talloc_set_destructor(const void *ptr, int (*destructor)(void *)); +int talloc_increase_ref_count(const void *ptr); +size_t talloc_reference_count(const void *ptr); +void *_talloc_reference(const void *context, const void *ptr); int talloc_unlink(const void *context, void *ptr); -void talloc_set_name(const void *ptr, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); +const char *talloc_set_name(const void *ptr, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); void talloc_set_name_const(const void *ptr, const char *name); void *talloc_named(const void *context, size_t size, const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); void *talloc_named_const(const void *context, size_t size, const char *name); const char *talloc_get_name(const void *ptr); void *talloc_check_name(const void *ptr, const char *name); -void talloc_report_depth(const void *ptr, FILE *f, int depth); void *talloc_parent(const void *ptr); void *talloc_init(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2); int talloc_free(void *ptr); +void talloc_free_children(void *ptr); void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name); -/* void *talloc_steal(const void *new_ctx, const void *ptr); */ -off_t talloc_total_size(const void *ptr); -off_t talloc_total_blocks(const void *ptr); +void *_talloc_steal(const void *new_ctx, const void *ptr); +size_t talloc_total_size(const void *ptr); +size_t talloc_total_blocks(const void *ptr); +void talloc_report_depth_cb(const void *ptr, int depth, int max_depth, + void (*callback)(const void *ptr, + int depth, int max_depth, + int is_ref, + void *private_data), + void *private_data); +void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f); void talloc_report_full(const void *ptr, FILE *f); void talloc_report(const void *ptr, FILE *f); void talloc_enable_null_tracking(void); +void talloc_disable_null_tracking(void); void talloc_enable_leak_report(void); void talloc_enable_leak_report_full(void); void *_talloc_zero(const void *ctx, size_t size, const char *name); @@ -130,8 +150,7 @@ char *talloc_append_string(const void *t, char *orig, const char *append); char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); -char *talloc_asprintf_append(char *s, - const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); +char *talloc_asprintf_append(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name); void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name); void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name); @@ -140,7 +159,7 @@ void *talloc_autofree_context(void); 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); +int talloc_is_parent(const void *context, const void *ptr); #endif diff --git a/source3/lib/talloc.c b/source3/lib/talloc.c index 0e223e8bbe..2fb8fb2530 100644 --- a/source3/lib/talloc.c +++ b/source3/lib/talloc.c @@ -1,4 +1,4 @@ -/* +/* Samba Unix SMB/CIFS implementation. Samba trivial allocation library - new interface @@ -6,11 +6,12 @@ NOTE: Please read talloc_guide.txt for full documentation Copyright (C) Andrew Tridgell 2004 - + Copyright (C) Stefan Metzmacher 2006 + ** NOTE! The following LGPL license applies to the talloc ** library. This does NOT imply that all of Samba is released ** under the LGPL - + This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either @@ -31,8 +32,9 @@ */ #ifdef _SAMBA_BUILD_ +#include "version.h" +#if (SAMBA_VERSION_MAJOR<4) #include "includes.h" -#if ((SAMBA_VERSION_MAJOR==3)&&(SAMBA_VERSION_MINOR<9)) /* This is to circumvent SAMBA3's paranoid malloc checker. Here in this file * we trust ourselves... */ #ifdef malloc @@ -41,18 +43,32 @@ #ifdef realloc #undef realloc #endif -#endif -#else +#define _TALLOC_SAMBA3 +#endif /* (SAMBA_VERSION_MAJOR<4) */ +#endif /* _SAMBA_BUILD_ */ + +#ifndef _TALLOC_SAMBA3 +#include "config.h" + #include #include #include -#include +#include +#ifdef HAVE_STDINT_H #include -#include "talloc.h" -/* assume a modern system */ -#define HAVE_VA_COPY #endif +#if defined(HAVE_STDARG_H) +#include +#elif defined (HAVE_VARARGS_H) +#include +#else +#error "no var arg header" +#endif + +#include "talloc.h" +#endif /* not _TALLOC_SAMBA3 */ + /* use this to force every realloc to change the pointer, to stress test code that might not cope */ #define ALWAYS_REALLOC 0 @@ -82,11 +98,9 @@ talloc_enable_leak_report_full() is called, otherwise it remains NULL */ -static const void *null_context; +static void *null_context; static void *cleanup_context; -static void *talloc_steal(const void *new_ctx, const void *ptr); - struct talloc_reference_handle { struct talloc_reference_handle *next, *prev; void *ptr; @@ -215,7 +229,7 @@ void *_talloc(const void *context, size_t size) if the destructor fails then the free is failed, and the memory can be continued to be used */ -void talloc_set_destructor(const void *ptr, int (*destructor)(void *)) +void _talloc_set_destructor(const void *ptr, int (*destructor)(void *)) { struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); tc->destructor = destructor; @@ -224,25 +238,21 @@ void talloc_set_destructor(const void *ptr, int (*destructor)(void *)) /* increase the reference count on a piece of memory. */ -void talloc_increase_ref_count(const void *ptr) +int talloc_increase_ref_count(const void *ptr) { - talloc_reference(null_context, ptr); + if (!talloc_reference(null_context, ptr)) { + return -1; + } + return 0; } /* helper for talloc_reference() */ -static int talloc_reference_destructor(void *ptr) +static int talloc_reference_destructor(struct talloc_reference_handle *handle) { - struct talloc_reference_handle *handle = - (struct talloc_reference_handle *)ptr; - struct talloc_chunk *tc1 = talloc_chunk_from_ptr(ptr); - struct talloc_chunk *tc2 = talloc_chunk_from_ptr(handle->ptr); - if (tc1->destructor != (talloc_destructor_t)-1) { - tc1->destructor = NULL; - } - _TLIST_REMOVE(tc2->refs, handle); - talloc_free(handle); + struct talloc_chunk *ptr_tc = talloc_chunk_from_ptr(handle->ptr); + _TLIST_REMOVE(ptr_tc->refs, handle); return 0; } @@ -255,16 +265,16 @@ static int talloc_reference_destructor(void *ptr) same underlying data, and you want to be able to free the two instances separately, and in either order */ -void *talloc_reference(const void *context, const void *ptr) +void *_talloc_reference(const void *context, const void *ptr) { struct talloc_chunk *tc; struct talloc_reference_handle *handle; if (ptr == NULL) return NULL; tc = talloc_chunk_from_ptr(ptr); - handle = (struct talloc_reference_handle *)talloc_named_const( - context, sizeof(*handle), TALLOC_MAGIC_REFERENCE); - + handle = (struct talloc_reference_handle *)talloc_named_const(context, + sizeof(struct talloc_reference_handle), + TALLOC_MAGIC_REFERENCE); if (handle == NULL) return NULL; /* note that we hang the destructor off the handle, not the @@ -302,10 +312,7 @@ static int talloc_unreference(const void *context, const void *ptr) return -1; } - talloc_set_destructor(h, NULL); - _TLIST_REMOVE(tc->refs, h); - talloc_free(h); - return 0; + return talloc_free(h); } /* @@ -364,26 +371,29 @@ int talloc_unlink(const void *context, void *ptr) /* add a name to an existing pointer - va_list version */ -static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); +static const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); -static void talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) +static const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) { struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); tc->name = talloc_vasprintf(ptr, fmt, ap); if (tc->name) { talloc_set_name_const(tc->name, ".name"); } + return tc->name; } /* add a name to an existing pointer */ -void talloc_set_name(const void *ptr, const char *fmt, ...) +const char *talloc_set_name(const void *ptr, const char *fmt, ...) { + const char *name; va_list ap; va_start(ap, fmt); - talloc_set_name_v(ptr, fmt, ap); + name = talloc_set_name_v(ptr, fmt, ap); va_end(ap); + return name; } /* @@ -405,14 +415,20 @@ void *talloc_named(const void *context, size_t size, const char *fmt, ...) { va_list ap; void *ptr; + const char *name; ptr = _talloc(context, size); if (ptr == NULL) return NULL; va_start(ap, fmt); - talloc_set_name_v(ptr, fmt, ap); + name = talloc_set_name_v(ptr, fmt, ap); va_end(ap); + if (name == NULL) { + talloc_free(ptr); + return NULL; + } + return ptr; } @@ -474,16 +490,20 @@ void *talloc_init(const char *fmt, ...) { va_list ap; void *ptr; - - talloc_enable_null_tracking(); + const char *name; ptr = _talloc(NULL, 0); if (ptr == NULL) return NULL; va_start(ap, fmt); - talloc_set_name_v(ptr, fmt, ap); + name = talloc_set_name_v(ptr, fmt, ap); va_end(ap); + if (name == NULL) { + talloc_free(ptr); + return NULL; + } + return ptr; } @@ -535,6 +555,7 @@ void talloc_free_children(void *ptr) int talloc_free(void *ptr) { struct talloc_chunk *tc; + int old_errno; if (ptr == NULL) { return -1; @@ -544,9 +565,15 @@ int talloc_free(void *ptr) if (tc->refs) { int is_child; - struct talloc_reference_handle *handle = tc->refs; - is_child = talloc_is_parent(handle, (const char *)handle->ptr); - talloc_reference_destructor(tc->refs); + /* check this is a reference from a child or grantchild + * back to it's parent or grantparent + * + * in that case we need to remove the reference and + * call another instance of talloc_free() on the current + * pointer. + */ + is_child = talloc_is_parent(tc->refs, ptr); + talloc_free(tc->refs); if (is_child) { return talloc_free(ptr); } @@ -571,10 +598,6 @@ int talloc_free(void *ptr) tc->destructor = NULL; } - tc->flags |= TALLOC_FLAG_LOOP; - - talloc_free_children(ptr); - if (tc->parent) { _TLIST_REMOVE(tc->parent->child, tc); if (tc->parent->child) { @@ -585,9 +608,13 @@ int talloc_free(void *ptr) if (tc->next) tc->next->prev = tc->prev; } - tc->flags |= TALLOC_FLAG_FREE; + tc->flags |= TALLOC_FLAG_LOOP; + talloc_free_children(ptr); + tc->flags |= TALLOC_FLAG_FREE; + old_errno = errno; free(tc); + errno = old_errno; return 0; } @@ -644,10 +671,10 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n tc = (struct talloc_chunk *)new_ptr; tc->flags &= ~TALLOC_FLAG_FREE; if (tc->parent) { - tc->parent->child = (struct talloc_chunk *)new_ptr; + tc->parent->child = tc; } if (tc->child) { - tc->child->parent = (struct talloc_chunk *)new_ptr; + tc->child->parent = tc; } if (tc->prev) { @@ -668,7 +695,7 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n ptr on success, or NULL if it could not be transferred. passing NULL as ptr will always return NULL with no side effects. */ -static void *talloc_steal(const void *new_ctx, const void *ptr) +void *_talloc_steal(const void *new_ctx, const void *ptr) { struct talloc_chunk *tc, *new_tc; @@ -723,11 +750,11 @@ static void *talloc_steal(const void *new_ctx, const void *ptr) /* return the total size of a talloc pool (subtree) */ -off_t talloc_total_size(const void *ptr) +size_t talloc_total_size(const void *ptr) { - off_t total = 0; + size_t total = 0; struct talloc_chunk *c, *tc; - + if (ptr == NULL) { ptr = null_context; } @@ -756,9 +783,9 @@ off_t talloc_total_size(const void *ptr) /* return the total number of blocks in a talloc pool (subtree) */ -off_t talloc_total_blocks(const void *ptr) +size_t talloc_total_blocks(const void *ptr) { - off_t total = 0; + size_t total = 0; struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); if (tc->flags & TALLOC_FLAG_LOOP) { @@ -780,11 +807,11 @@ off_t talloc_total_blocks(const void *ptr) /* return the number of external references to a pointer */ -static int talloc_reference_count(const void *ptr) +size_t talloc_reference_count(const void *ptr) { struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); struct talloc_reference_handle *h; - int ret = 0; + size_t ret = 0; for (h=tc->refs;h;h=h->next) { ret++; @@ -795,81 +822,93 @@ static int talloc_reference_count(const void *ptr) /* report on memory usage by all children of a pointer, giving a full tree view */ -void talloc_report_depth(const void *ptr, FILE *f, int depth) +void talloc_report_depth_cb(const void *ptr, int depth, int max_depth, + void (*callback)(const void *ptr, + int depth, int max_depth, + int is_ref, + void *private_data), + void *private_data) { - struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); + struct talloc_chunk *c, *tc; + + if (ptr == NULL) { + ptr = null_context; + } + if (ptr == NULL) return; + + tc = talloc_chunk_from_ptr(ptr); if (tc->flags & TALLOC_FLAG_LOOP) { return; } - tc->flags |= TALLOC_FLAG_LOOP; + callback(ptr, depth, max_depth, 0, private_data); + + if (max_depth >= 0 && depth >= max_depth) { + return; + } + tc->flags |= TALLOC_FLAG_LOOP; for (c=tc->child;c;c=c->next) { if (c->name == TALLOC_MAGIC_REFERENCE) { - struct talloc_reference_handle *handle = - (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c); - const char *name2 = talloc_get_name(handle->ptr); - fprintf(f, "%*sreference to: %s\n", depth*4, "", name2); + struct talloc_reference_handle *h = (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c); + callback(h->ptr, depth + 1, max_depth, 1, private_data); } else { - const char *name = talloc_get_name(TC_PTR_FROM_CHUNK(c)); - fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n", - depth*4, "", - name, - (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)), - (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)), - talloc_reference_count(TC_PTR_FROM_CHUNK(c))); - talloc_report_depth(TC_PTR_FROM_CHUNK(c), f, depth+1); + talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c), depth + 1, max_depth, callback, private_data); } } tc->flags &= ~TALLOC_FLAG_LOOP; } -/* - report on memory usage by all children of a pointer, giving a full tree view -*/ -void talloc_report_full(const void *ptr, FILE *f) +static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_f) { - if (ptr == NULL) { - ptr = null_context; + const char *name = talloc_get_name(ptr); + FILE *f = (FILE *)_f; + + if (is_ref) { + fprintf(f, "%*sreference to: %s\n", depth*4, "", name); + return; + } + + if (depth == 0) { + fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n", + (max_depth < 0 ? "full " :""), name, + (unsigned long)talloc_total_size(ptr), + (unsigned long)talloc_total_blocks(ptr)); + return; } - if (ptr == NULL) return; - fprintf(f,"full talloc report on '%s' (total %lu bytes in %lu blocks)\n", - talloc_get_name(ptr), + fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n", + depth*4, "", + name, (unsigned long)talloc_total_size(ptr), - (unsigned long)talloc_total_blocks(ptr)); + (unsigned long)talloc_total_blocks(ptr), + talloc_reference_count(ptr)); +} - talloc_report_depth(ptr, f, 1); +/* + report on memory usage by all children of a pointer, giving a full tree view +*/ +void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f) +{ + talloc_report_depth_cb(ptr, depth, max_depth, talloc_report_depth_FILE_helper, f); fflush(f); } +/* + report on memory usage by all children of a pointer, giving a full tree view +*/ +void talloc_report_full(const void *ptr, FILE *f) +{ + talloc_report_depth_file(ptr, 0, -1, f); +} + /* report on memory usage by all children of a pointer */ void talloc_report(const void *ptr, FILE *f) { - struct talloc_chunk *c, *tc; - - if (ptr == NULL) { - ptr = null_context; - } - if (ptr == NULL) return; - - fprintf(f,"talloc report on '%s' (total %lu bytes in %lu blocks)\n", - talloc_get_name(ptr), - (unsigned long)talloc_total_size(ptr), - (unsigned long)talloc_total_blocks(ptr)); - - tc = talloc_chunk_from_ptr(ptr); - - for (c=tc->child;c;c=c->next) { - fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n", - talloc_get_name(TC_PTR_FROM_CHUNK(c)), - (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)), - (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c))); - } - fflush(f); + talloc_report_depth_file(ptr, 0, 1, f); } /* @@ -892,16 +931,6 @@ static void talloc_report_null_full(void) } } -/* - free allocated global memory -*/ - -void talloc_nc_free(void) -{ - if ( null_context ) - talloc_free( (void*)null_context ); -} - /* enable tracking of the NULL context */ @@ -912,75 +941,15 @@ void talloc_enable_null_tracking(void) } } -#ifdef _SAMBA_BUILD_ -/* Ugly calls to Samba-specific sprintf_append... JRA. */ - /* - report on memory usage by all children of a pointer, giving a full tree view + disable tracking of the NULL context */ -static void talloc_report_depth_str(const void *ptr, char **pps, ssize_t *plen, size_t *pbuflen, int depth) +void talloc_disable_null_tracking(void) { - struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); - - if (tc->flags & TALLOC_FLAG_LOOP) { - return; - } - - tc->flags |= TALLOC_FLAG_LOOP; - - for (c=tc->child;c;c=c->next) { - if (c->name == TALLOC_MAGIC_REFERENCE) { - struct talloc_reference_handle *handle = - (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c); - const char *name2 = talloc_get_name(handle->ptr); - - sprintf_append(NULL, pps, plen, pbuflen, - "%*sreference to: %s\n", depth*4, "", name2); - - } else { - const char *name = talloc_get_name(TC_PTR_FROM_CHUNK(c)); - - sprintf_append(NULL, pps, plen, pbuflen, - "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n", - depth*4, "", - name, - (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)), - (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)), - talloc_reference_count(TC_PTR_FROM_CHUNK(c))); - - talloc_report_depth_str(TC_PTR_FROM_CHUNK(c), pps, plen, pbuflen, depth+1); - } - } - tc->flags &= ~TALLOC_FLAG_LOOP; + talloc_free(null_context); + null_context = NULL; } -/* - report on memory usage by all children of a pointer -*/ -char *talloc_describe_all(void) -{ - ssize_t len = 0; - size_t buflen = 512; - char *s = NULL; - - if (null_context == NULL) { - return NULL; - } - - sprintf_append(NULL, &s, &len, &buflen, - "full talloc report on '%s' (total %lu bytes in %lu blocks)\n", - talloc_get_name(null_context), - (unsigned long)talloc_total_size(null_context), - (unsigned long)talloc_total_blocks(null_context)); - - if (!s) { - return NULL; - } - talloc_report_depth_str(null_context, &s, &len, &buflen, 1); - return s; -} -#endif - /* enable leak reporting on exit */ @@ -1086,13 +1055,11 @@ char *talloc_strndup(const void *t, const char *p, size_t n) return ret; } -#ifndef VA_COPY -#ifdef HAVE_VA_COPY -#define VA_COPY(dest, src) va_copy(dest, src) -#elif defined(HAVE___VA_COPY) -#define VA_COPY(dest, src) __va_copy(dest, src) +#ifndef HAVE_VA_COPY +#ifdef HAVE___VA_COPY +#define va_copy(dest, src) __va_copy(dest, src) #else -#define VA_COPY(dest, src) (dest) = (src) +#define va_copy(dest, src) (dest) = (src) #endif #endif @@ -1103,7 +1070,7 @@ char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) va_list ap2; char c; - VA_COPY(ap2, ap); + va_copy(ap2, ap); /* this call looks strange, but it makes it work on older solaris boxes */ if ((len = vsnprintf(&c, 1, fmt, ap2)) < 0) { @@ -1112,7 +1079,7 @@ char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) ret = (char *)_talloc(t, len+1); if (ret) { - VA_COPY(ap2, ap); + va_copy(ap2, ap); vsnprintf(ret, len+1, fmt, ap2); talloc_set_name_const(ret, ret); } @@ -1142,12 +1109,12 @@ char *talloc_asprintf(const void *t, const char *fmt, ...) * and return @p s, which may have moved. Good for gradually * accumulating output into a string buffer. **/ - char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) { struct talloc_chunk *tc; int len, s_len; va_list ap2; + char c; if (s == NULL) { return talloc_vasprintf(NULL, fmt, ap); @@ -1155,10 +1122,10 @@ char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) tc = talloc_chunk_from_ptr(s); - VA_COPY(ap2, ap); + va_copy(ap2, ap); s_len = tc->size - 1; - if ((len = vsnprintf(NULL, 0, fmt, ap2)) <= 0) { + if ((len = vsnprintf(&c, 1, fmt, ap2)) <= 0) { /* Either the vsnprintf failed or the format resulted in * no characters being formatted. In the former case, we * ought to return NULL, in the latter we ought to return @@ -1171,7 +1138,7 @@ char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) s = talloc_realloc(NULL, s, char, s_len + len+1); if (!s) return NULL; - VA_COPY(ap2, ap); + va_copy(ap2, ap); vsnprintf(s+s_len, len+1, fmt, ap2); talloc_set_name_const(s, s); @@ -1290,7 +1257,6 @@ void *talloc_find_parent_byname(const void *context, const char *name) if (tc) { tc = tc->parent; } - } return NULL; } @@ -1321,7 +1287,7 @@ void talloc_show_parents(const void *context, FILE *file) /* return 1 if ptr is a parent of context */ -int talloc_is_parent(const void *context, const char *ptr) +int talloc_is_parent(const void *context, const void *ptr) { struct talloc_chunk *tc; diff --git a/source3/lib/tallocmsg.c b/source3/lib/tallocmsg.c index e4364f1ff7..599d60737d 100644 --- a/source3/lib/tallocmsg.c +++ b/source3/lib/tallocmsg.c @@ -25,6 +25,40 @@ * Glue code between talloc profiling and the Samba messaging system. **/ +struct msg_pool_usage_state { + ssize_t len; + size_t buflen; + char *s; +}; + +static void msg_pool_usage_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_s) +{ + const char *name = talloc_get_name(ptr); + struct msg_pool_usage_state *state = (struct msg_pool_usage_state *)_s; + + if (is_ref) { + sprintf_append(NULL, &state->s, &state->len, &state->buflen, + "%*sreference to: %s\n", depth*4, "", name); + return; + } + + if (depth == 0) { + sprintf_append(NULL, &state->s, &state->len, &state->buflen, + "%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n", + (max_depth < 0 ? "full " :""), name, + (unsigned long)talloc_total_size(ptr), + (unsigned long)talloc_total_blocks(ptr)); + return; + } + + sprintf_append(NULL, &state->s, &state->len, &state->buflen, + "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n", + depth*4, "", + name, + (unsigned long)talloc_total_size(ptr), + (unsigned long)talloc_total_blocks(ptr), + talloc_reference_count(ptr)); +} /** * Respond to a POOL_USAGE message by sending back string form of memory @@ -33,21 +67,26 @@ void msg_pool_usage(int msg_type, struct process_id src_pid, void *UNUSED(buf), size_t UNUSED(len)) { - char *reply = NULL; + struct msg_pool_usage_state state; SMB_ASSERT(msg_type == MSG_REQ_POOL_USAGE); DEBUG(2,("Got POOL_USAGE\n")); - reply = talloc_describe_all(); - if (!reply) { + state.len = 0; + state.buflen = 512; + state.s = NULL; + + talloc_report_depth_cb(NULL, 0, -1, msg_pool_usage_helper, &state); + + if (!state.s) { return; } message_send_pid(src_pid, MSG_POOL_USAGE, - reply, strlen(reply)+1, True); + state.s, strlen(state.s)+1, True); - SAFE_FREE(reply); + SAFE_FREE(state.s); } /** diff --git a/source3/lib/util.c b/source3/lib/util.c index 20ff4514a0..d650d0ed8b 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -202,7 +202,7 @@ void gfree_all( void ) gfree_messages(); /* release the talloc null_context memory last */ - talloc_nc_free(); + talloc_disable_null_tracking(); } const char *my_netbios_names(int i) -- cgit