Subject: lib/37170: deadlock between atexit and jemalloc
To: None <lib-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: None <yamt@mwd.biglobe.ne.jp>
List: netbsd-bugs
Date: 10/22/2007 02:45:00
>Number: 37170
>Category: lib
>Synopsis: deadlock between atexit and jemalloc
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: lib-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Mon Oct 22 02:45:00 +0000 2007
>Originator: YAMAMOTO Takashi <yamt@mwd.biglobe.ne.jp>
>Release: NetBSD 4.99.34
>Organization:
>Environment:
NetBSd 4.99.34 amd64
>Description:
jemalloc with MALLOC_OPTIONS=P uses atexit on initialization.
atexit uses malloc.
>How-To-Repeat:
run C++ programs with MALLOC_OPTIONS=P.
>Fix:
while the following patch avoids the deadlock,
i don't understand the comment in atexit_handler_alloc.
/*
* Either no static slot was free, or this is a cxa_atexit
* handler. Allocate a new one. We keep the atexit_mutex
* held to prevent handlers from being run while we (potentially)
* block in malloc().
*/
Index: atexit.c
===================================================================
RCS file: /cvsroot/src/lib/libc/stdlib/atexit.c,v
retrieving revision 1.19
diff -u -p -r1.19 atexit.c
--- atexit.c 8 Aug 2007 01:05:34 -0000 1.19
+++ atexit.c 21 Oct 2007 22:33:37 -0000
@@ -96,13 +96,16 @@ static struct atexit_handler *
atexit_handler_alloc(void *dso)
{
struct atexit_handler *ah;
+ struct atexit_handler *ah_malloced = NULL;
int i;
+retry:
if (dso == NULL) {
for (i = 0; i < NSTATIC_HANDLERS; i++) {
ah = &atexit_handler0[i];
if (ah->ah_atexit == NULL && ah->ah_next == NULL) {
/* Slot is free. */
+ free(ah_malloced);
return (ah);
}
}
@@ -114,8 +117,13 @@ atexit_handler_alloc(void *dso)
* held to prevent handlers from being run while we (potentially)
* block in malloc().
*/
- ah = malloc(sizeof(*ah));
- return (ah);
+ if (ah_malloced == NULL) {
+ mutex_unlock(&atexit_mutex);
+ ah_malloced = malloc(sizeof(*ah));
+ mutex_lock(&atexit_mutex);
+ goto retry;
+ }
+ return (ah_malloced);
}
/*
Index: jemalloc.c
===================================================================
RCS file: /cvsroot/src/lib/libc/stdlib/jemalloc.c,v
retrieving revision 1.9
diff -u -p -r1.9 jemalloc.c
--- jemalloc.c 19 Oct 2007 19:28:57 -0000 1.9
+++ jemalloc.c 21 Oct 2007 22:33:37 -0000
@@ -3494,12 +3494,6 @@ malloc_init_hard(void)
}
}
- /* Take care to call atexit() only once. */
- if (opt_print_stats) {
- /* Print statistics at exit. */
- atexit(malloc_print_stats);
- }
-
/* Set variables according to the value of opt_small_max_2pow. */
if (opt_small_max_2pow < opt_quantum_2pow)
opt_small_max_2pow = opt_quantum_2pow;
@@ -3642,6 +3636,13 @@ malloc_init_hard(void)
malloc_mutex_init(&arenas_mtx);
malloc_initialized = true;
+
+ /* Take care to call atexit() only once. */
+ if (opt_print_stats) {
+ /* Print statistics at exit. */
+ atexit(malloc_print_stats);
+ }
+
malloc_mutex_unlock(&init_lock);
return (false);
}
>Unformatted: