summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/lib/cmdline/popt_common.c13
-rw-r--r--source4/lib/talloc.c72
2 files changed, 80 insertions, 5 deletions
diff --git a/source4/lib/cmdline/popt_common.c b/source4/lib/cmdline/popt_common.c
index e2deb5db96..f98c460642 100644
--- a/source4/lib/cmdline/popt_common.c
+++ b/source4/lib/cmdline/popt_common.c
@@ -34,7 +34,7 @@
*/
-enum {OPT_OPTION=1};
+enum {OPT_OPTION=1,OPT_LEAK_CHECK=2};
static struct cmdline_auth_info cmdline_auth_info;
@@ -116,6 +116,10 @@ static void popt_common_callback(poptContext con,
exit(1);
}
break;
+
+ case OPT_LEAK_CHECK:
+ talloc_enable_leak_check();
+ break;
}
}
@@ -132,10 +136,11 @@ struct poptOption popt_common_connection[] = {
struct poptOption popt_common_samba[] = {
{ NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, popt_common_callback },
- { "debuglevel", 'd', POPT_ARG_STRING, NULL, 'd', "Set debug level", "DEBUGLEVEL" },
- { "configfile", 's', POPT_ARG_STRING, NULL, 's', "Use alternative configuration file", "CONFIGFILE" },
- { "option", 0, POPT_ARG_STRING, NULL, OPT_OPTION, "Set smb.conf option from command line", "name=value" },
+ { "debuglevel", 'd', POPT_ARG_STRING, NULL, 'd', "Set debug level", "DEBUGLEVEL" },
+ { "configfile", 's', POPT_ARG_STRING, NULL, 's', "Use alternative configuration file", "CONFIGFILE" },
+ { "option", 0, POPT_ARG_STRING, NULL, OPT_OPTION, "Set smb.conf option from command line", "name=value" },
{ "log-basename", 'l', POPT_ARG_STRING, NULL, 'l', "Basename for log/debug files", "LOGFILEBASE" },
+ { "leak-check", 0, POPT_ARG_NONE, NULL, OPT_LEAK_CHECK, "enable talloc leak checking", NULL },
POPT_TABLEEND
};
diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c
index c236834d91..114d0de43b 100644
--- a/source4/lib/talloc.c
+++ b/source4/lib/talloc.c
@@ -30,6 +30,8 @@
#define TALLOC_MAGIC 0xe814ec4f
#define TALLOC_MAGIC_FREE 0x7faebef3
+static void *null_context;
+
struct talloc_chunk {
struct talloc_chunk *next, *prev;
struct talloc_chunk *parent, *child;
@@ -61,6 +63,10 @@ void *talloc(void *context, size_t size)
{
struct talloc_chunk *tc;
+ if (context == NULL) {
+ context = null_context;
+ }
+
if (size >= MAX_TALLOC_SIZE) {
return NULL;
}
@@ -165,6 +171,18 @@ void *talloc_named(void *context, size_t size,
}
/*
+ return the name of a talloc ptr, or "UNNAMED"
+*/
+const char *talloc_get_name(void *ptr)
+{
+ struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+ if (tc->name) {
+ return tc->name;
+ }
+ return "UNNAMED";
+}
+
+/*
this is for compatibility with older versions of talloc
*/
void *talloc_init(const char *fmt, ...) _PRINTF_ATTRIBUTE(1,2)
@@ -327,7 +345,7 @@ void *talloc_steal(void *new_ctx, void *ptr)
/*
return the total size of a talloc pool (subtree)
*/
-off_t talloc_total_size(void *ptr)
+static off_t talloc_total_size(void *ptr)
{
off_t total = 0;
struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
@@ -339,6 +357,58 @@ off_t talloc_total_size(void *ptr)
return total;
}
+/*
+ return the total number of blocks in a talloc pool (subtree)
+*/
+static off_t talloc_total_blocks(void *ptr)
+{
+ off_t total = 0;
+ struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
+
+ total++;
+ for (c=tc->child;c;c=c->next) {
+ total += talloc_total_blocks(c+1);
+ }
+ return total;
+}
+
+/*
+ report on memory usage by all children of a pointer
+*/
+void talloc_report(void *ptr, FILE *f)
+{
+ struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
+
+ 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));
+
+ for (c=tc->child;c;c=c->next) {
+ fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n",
+ talloc_get_name(c+1),
+ (unsigned long)talloc_total_size(c+1),
+ (unsigned long)talloc_total_blocks(c+1));
+ }
+
+}
+
+/*
+ report on any memory hanging off the null context
+*/
+static void talloc_report_all(void)
+{
+ talloc_report(null_context, stderr);
+}
+
+/*
+ enable leak reporting on exit
+*/
+void talloc_enable_leak_check(void)
+{
+ null_context = talloc_named(NULL, 0, "null_context");
+ atexit(talloc_report_all);
+}
/*
talloc and zero memory.