This is the mail archive of the libc-hacker@sources.redhat.com mailing list for the glibc project.

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[PATCH] Fix memusage (take 2)


On Tue, Aug 07, 2001 at 10:34:13AM -0700, Ulrich Drepper wrote:
> Jakub Jelinek <jakub@redhat.com> writes:
> 
> > memusage does not work with any threaded program.
> 
> This patch works around the problems the code has with the current
> implementation of ld.so.  As soon as the latter is changed it'll fail.
> At least all functions should get the if (initializing) trap door.

Is this better? It still assumes that nothing bad happens if any allocation
routine returns NULL when dlsym is called (which is true ATM) and that
first pthread_create either calls malloc, or happens after libmemusage.so
constructor is executed, but otherwise it does not rely on too many other
things. E.g. the allocation routines can be called from other constructors
which are run before memusage's one, etc.
If the first assumption (dlsym fails if *alloc returns NULL) was false,
memusage would either have to come with its fallback malloc/calloc etc. e.g.
using mmap (and have free check that range), or they could e.g. call
__libc_malloc/__libc_calloc etc. in such a case (but record the addresses
returned that way, so that they'd be freed with __libc_free).
If the second assumption was false, __libc_once would have to be used.

2001-08-07  Jakub Jelinek  <jakub@redhat.com>

	* malloc/memusage.c (initialized): New variable.
	(init): If not yet initialized, call me().
	(me): Do all dlsym calls here.
	(malloc, realloc, calloc, free): If not yet initialized,
	call me(). If in the middle of initializing, return NULL or
	do nothing.

--- libc/malloc/memusage.c.jj	Mon Jul  9 15:42:54 2001
+++ libc/malloc/memusage.c	Tue Aug  7 15:45:59 2001
@@ -82,6 +83,7 @@ static size_t buffer_size;
 static int fd = -1;
 
 static int not_me;
+static int initialized;
 extern const char *__progname;
 
 struct entry
@@ -163,6 +165,8 @@ __attribute__ ((constructor))
 init (void)
 {
   start_sp = GETSP ();
+  if (! initialized)
+    me ();
 }
 
 
@@ -187,6 +191,16 @@ me (void)
 {
   const char *env = getenv ("MEMUSAGE_PROG_NAME");
   size_t prog_len = strlen (__progname);
+
+  if (!start_sp)
+    start_sp = GETSP ();
+  initialized = -1;
+  mallocp = (void *(*) (size_t)) dlsym (RTLD_NEXT, "malloc");
+  reallocp = (void *(*) (void *, size_t)) dlsym (RTLD_NEXT, "realloc");
+  callocp = (void *(*) (size_t, size_t)) dlsym (RTLD_NEXT, "calloc");
+  freep = (void (*) (void *)) dlsym (RTLD_NEXT, "free");
+  initialized = 1;
+
   if (env != NULL)
     {
       /* Check for program name.  */
@@ -261,10 +275,11 @@ malloc (size_t len)
   struct header *result = NULL;
 
   /* Determine real implementation if not already happened.  */
-  if (mallocp == NULL)
+  if (initialized <= 0)
     {
+      if (initialized == -1)
+	return NULL;
       me ();
-      mallocp = (void *(*) (size_t)) dlsym (RTLD_NEXT, "malloc");
     }
 
   /* If this is not the correct program just use the normal function.  */
@@ -309,10 +324,11 @@ realloc (void *old, size_t len)
   size_t old_len;
 
   /* Determine real implementation if not already happened.  */
-  if (reallocp == NULL)
+  if (initialized <= 0)
     {
+      if (initialized == -1)
+	return NULL;
       me ();
-      reallocp = (void *(*) (void *, size_t)) dlsym (RTLD_NEXT, "realloc");
     }
 
   /* If this is not the correct program just use the normal function.  */
@@ -379,23 +395,17 @@ calloc (size_t n, size_t len)
   struct header *result;
   size_t size = n * len;
 
-  /* Determine real implementation if not already happened.  We are
-     searching for the `malloc' implementation since it is not always
-     efficiently possible to use `calloc' because we have to add a bit
-     room to the allocation to put the header in.  */
-  if (mallocp == NULL)
+  /* Determine real implementation if not already happened.  */
+  if (initialized <= 0)
     {
+      if (initialized == -1)
+	return NULL;
       me ();
-      mallocp = (void *(*) (size_t)) dlsym (RTLD_NEXT, "malloc");
     }
 
   /* If this is not the correct program just use the normal function.  */
   if (not_me)
-    {
-      callocp = (void *(*) (size_t, size_t)) dlsym (RTLD_NEXT, "calloc");
-
-      return (*callocp) (n, len);
-    }
+    return (*callocp) (n, len);
 
   /* Keep track of number of calls.  */
   ++calls[idx_calloc];
@@ -442,10 +452,11 @@ free (void *ptr)
     }
 
   /* Determine real implementation if not already happened.  */
-  if (freep == NULL)
+  if (initialized <= 0)
     {
+      if (initialized == -1)
+	return;
       me ();
-      freep = (void (*) (void *)) dlsym (RTLD_NEXT, "free");
     }
 
   /* If this is not the correct program just use the normal function.  */


	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]