NetBSD Problem Report #37170

From yamt@mwd.biglobe.ne.jp  Mon Oct 22 02:44:59 2007
Return-Path: <yamt@mwd.biglobe.ne.jp>
Received: from mail.netbsd.org (mail.netbsd.org [204.152.190.11])
	by narn.NetBSD.org (Postfix) with ESMTP id 46D9863B8FE
	for <gnats-bugs@gnats.NetBSD.org>; Mon, 22 Oct 2007 02:44:59 +0000 (UTC)
Message-Id: <20071021223939.5AA0A11702@yamt.dyndns.org>
Date: Mon, 22 Oct 2007 07:39:39 +0900 (JST)
From: yamt@mwd.biglobe.ne.jp
Reply-To: yamt@mwd.biglobe.ne.jp
To: gnats-bugs@NetBSD.org
Subject: deadlock between atexit and jemalloc
X-Send-Pr-Version: 3.95

>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:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.