svn commit: samba r2640 - in branches/SAMBA_4_0/source/lib: . cmdline

tridge at samba.org tridge at samba.org
Sun Sep 26 01:14:26 GMT 2004


Author: tridge
Date: 2004-09-26 01:14:26 +0000 (Sun, 26 Sep 2004)
New Revision: 2640

WebSVN: http://websvn.samba.org/websvn/changeset.php?rep=samba&path=/branches/SAMBA_4_0/source/lib&rev=2640&nolog=1

Log:
valgrind does a great job on some types of memory leaks, but is slow
and can't properly handle leaks of doubly linked lists which we use a
lot (as the memory is always reachable). Even with --show-reachable
its hard to track leaks down sometimes.

I realised that talloc does have the necessary information to track
these, and by using the cascading property of the new talloc it can
report on leaks in a much more succinct fashion than valgrind can.

I have added a new samba option --leak-check that applies to all Samba
tools. When enabled it prints a leak report summarising all top level
contexts that are present when the program exits. A typical report
looks like this:

talloc report on 'null_context' (total 1071 bytes in 52 blocks)
        iconv(CP850,UTF8)              contains     43 bytes in   3 blocks
        UNNAMED                        contains     24 bytes in   1 blocks
        UNNAMED                        contains     24 bytes in   1 blocks
        dcesrv_init                    contains    604 bytes in  26 blocks
        server_service                 contains    120 bytes in   6 blocks
        UNNAMED                        contains     24 bytes in   1 blocks
        UNNAMED                        contains     24 bytes in   1 blocks
        server_service                 contains    104 bytes in   4 blocks
        server_context                 contains     12 bytes in   2 blocks
        iconv(UTF8,UTF-16LE)           contains     46 bytes in   3 blocks
        iconv(UTF-16LE,UTF8)           contains     46 bytes in   3 blocks

the numbers are recursive summaries for all the memory hanging off each context. 

this option is not thread safe when used, but the code is thread safe
if the option is not given, so I don't think thats a problem.

Modified:
   branches/SAMBA_4_0/source/lib/cmdline/popt_common.c
   branches/SAMBA_4_0/source/lib/talloc.c


Changeset:
Modified: branches/SAMBA_4_0/source/lib/cmdline/popt_common.c
===================================================================
--- branches/SAMBA_4_0/source/lib/cmdline/popt_common.c	2004-09-26 01:09:04 UTC (rev 2639)
+++ branches/SAMBA_4_0/source/lib/cmdline/popt_common.c	2004-09-26 01:14:26 UTC (rev 2640)
@@ -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 @@
 			exit(1);
 		}
 		break;
+
+	case OPT_LEAK_CHECK:
+		talloc_enable_leak_check();
+		break;
 	}
 }
 
@@ -132,10 +136,11 @@
 
 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
 };
 

Modified: branches/SAMBA_4_0/source/lib/talloc.c
===================================================================
--- branches/SAMBA_4_0/source/lib/talloc.c	2004-09-26 01:09:04 UTC (rev 2639)
+++ branches/SAMBA_4_0/source/lib/talloc.c	2004-09-26 01:14:26 UTC (rev 2640)
@@ -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 @@
 {
 	struct talloc_chunk *tc;
 
+	if (context == NULL) {
+		context = null_context;
+	}
+
 	if (size >= MAX_TALLOC_SIZE) {
 		return NULL;
 	}
@@ -165,6 +171,18 @@
 }
 
 /*
+  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 @@
 /*
   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,7 +357,59 @@
 	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. 
 */



More information about the samba-cvs mailing list