aboutsummaryrefslogtreecommitdiff
path: root/malloc
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@gmail.com>2011-05-16 00:58:33 -0400
committerUlrich Drepper <drepper@gmail.com>2011-05-16 00:58:33 -0400
commit56e5eb4619a936a3b63ae71f89038d69becd2999 (patch)
treee6005c7864f9b4ecd3f3bdfcae9b5bad9c294045 /malloc
parent6ce7537960cf42a0a6b0fc70957d5ce2ba9838de (diff)
downloadglibc-56e5eb4619a936a3b63ae71f89038d69becd2999.tar
glibc-56e5eb4619a936a3b63ae71f89038d69becd2999.tar.gz
glibc-56e5eb4619a936a3b63ae71f89038d69becd2999.tar.bz2
glibc-56e5eb4619a936a3b63ae71f89038d69becd2999.zip
Avoid potential deadlock in mtrace
The _dl_addr function might have to call malloc which would lead to a deadlock. Avoid by calling _dl_addr early.
Diffstat (limited to 'malloc')
-rw-r--r--malloc/mtrace.c64
1 files changed, 41 insertions, 23 deletions
diff --git a/malloc/mtrace.c b/malloc/mtrace.c
index 51be396aaa..b55449f1ea 100644
--- a/malloc/mtrace.c
+++ b/malloc/mtrace.c
@@ -79,46 +79,59 @@ tr_break ()
}
libc_hidden_def (tr_break)
-static void tr_where (const __ptr_t) __THROW internal_function;
+static void tr_where (const __ptr_t, Dl_info *) __THROW internal_function;
static void
internal_function
-tr_where (caller)
+tr_where (caller, info)
const __ptr_t caller;
+ Dl_info *info;
{
if (caller != NULL)
{
-#ifdef HAVE_ELF
- Dl_info info;
- if (_dl_addr (caller, &info, NULL, NULL))
+ if (info != NULL)
{
char *buf = (char *) "";
- if (info.dli_sname != NULL)
+ if (info->dli_sname != NULL)
{
- size_t len = strlen (info.dli_sname);
+ size_t len = strlen (info->dli_sname);
buf = alloca (len + 6 + 2 * sizeof (void *));
buf[0] = '(';
- __stpcpy (_fitoa (caller >= (const __ptr_t) info.dli_saddr
- ? caller - (const __ptr_t) info.dli_saddr
- : (const __ptr_t) info.dli_saddr - caller,
- __stpcpy (__mempcpy (buf + 1, info.dli_sname,
+ __stpcpy (_fitoa (caller >= (const __ptr_t) info->dli_saddr
+ ? caller - (const __ptr_t) info->dli_saddr
+ : (const __ptr_t) info->dli_saddr - caller,
+ __stpcpy (__mempcpy (buf + 1, info->dli_sname,
len),
- caller >= (__ptr_t) info.dli_saddr
+ caller >= (__ptr_t) info->dli_saddr
? "+0x" : "-0x"),
16, 0),
")");
}
fprintf (mallstream, "@ %s%s%s[%p] ",
- info.dli_fname ?: "", info.dli_fname ? ":" : "",
+ info->dli_fname ?: "", info->dli_fname ? ":" : "",
buf, caller);
}
else
-#endif
fprintf (mallstream, "@ [%p] ", caller);
}
}
+
+static Dl_info *
+lock_and_info (const __ptr_t caller, Dl_info *mem)
+{
+ if (caller == NULL)
+ return NULL;
+
+ Dl_info *res = _dl_addr (caller, mem, NULL, NULL) ? mem : NULL;
+
+ __libc_lock_lock (lock);
+
+ return res;
+}
+
+
static void tr_freehook (__ptr_t, const __ptr_t) __THROW;
static void
tr_freehook (ptr, caller)
@@ -127,8 +140,10 @@ tr_freehook (ptr, caller)
{
if (ptr == NULL)
return;
- __libc_lock_lock (lock);
- tr_where (caller);
+
+ Dl_info mem;
+ Dl_info *info = lock_and_info (caller, &mem);
+ tr_where (caller, info);
/* Be sure to print it first. */
fprintf (mallstream, "- %p\n", ptr);
__libc_lock_unlock (lock);
@@ -152,7 +167,8 @@ tr_mallochook (size, caller)
{
__ptr_t hdr;
- __libc_lock_lock (lock);
+ Dl_info mem;
+ Dl_info *info = lock_and_info (caller, &mem);
__malloc_hook = tr_old_malloc_hook;
if (tr_old_malloc_hook != NULL)
@@ -161,7 +177,7 @@ tr_mallochook (size, caller)
hdr = (__ptr_t) malloc (size);
__malloc_hook = tr_mallochook;
- tr_where (caller);
+ tr_where (caller, info);
/* We could be printing a NULL here; that's OK. */
fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long int) size);
@@ -186,7 +202,8 @@ tr_reallochook (ptr, size, caller)
if (ptr == mallwatch)
tr_break ();
- __libc_lock_lock (lock);
+ Dl_info mem;
+ Dl_info *info = lock_and_info (caller, &mem);
__free_hook = tr_old_free_hook;
__malloc_hook = tr_old_malloc_hook;
@@ -199,7 +216,7 @@ tr_reallochook (ptr, size, caller)
__malloc_hook = tr_mallochook;
__realloc_hook = tr_reallochook;
- tr_where (caller);
+ tr_where (caller, info);
if (hdr == NULL)
/* Failed realloc. */
fprintf (mallstream, "! %p %#lx\n", ptr, (unsigned long int) size);
@@ -208,7 +225,7 @@ tr_reallochook (ptr, size, caller)
else
{
fprintf (mallstream, "< %p\n", ptr);
- tr_where (caller);
+ tr_where (caller, info);
fprintf (mallstream, "> %p %#lx\n", hdr, (unsigned long int) size);
}
@@ -229,7 +246,8 @@ tr_memalignhook (alignment, size, caller)
{
__ptr_t hdr;
- __libc_lock_lock (lock);
+ Dl_info mem;
+ Dl_info *info = lock_and_info (caller, &mem);
__memalign_hook = tr_old_memalign_hook;
__malloc_hook = tr_old_malloc_hook;
@@ -240,7 +258,7 @@ tr_memalignhook (alignment, size, caller)
__memalign_hook = tr_memalignhook;
__malloc_hook = tr_mallochook;
- tr_where (caller);
+ tr_where (caller, info);
/* We could be printing a NULL here; that's OK. */
fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long int) size);