From owner-svn-src-head@FreeBSD.ORG Mon Dec 1 10:20:59 2008 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 6FB921065676; Mon, 1 Dec 2008 10:20:59 +0000 (UTC) (envelope-from jasone@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 5DB9C8FC1E; Mon, 1 Dec 2008 10:20:59 +0000 (UTC) (envelope-from jasone@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id mB1AKx3R019798; Mon, 1 Dec 2008 10:20:59 GMT (envelope-from jasone@svn.freebsd.org) Received: (from jasone@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id mB1AKxwK019797; Mon, 1 Dec 2008 10:20:59 GMT (envelope-from jasone@svn.freebsd.org) Message-Id: <200812011020.mB1AKxwK019797@svn.freebsd.org> From: Jason Evans Date: Mon, 1 Dec 2008 10:20:59 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r185514 - head/lib/libc/stdlib X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 01 Dec 2008 10:20:59 -0000 Author: jasone Date: Mon Dec 1 10:20:59 2008 New Revision: 185514 URL: http://svn.freebsd.org/changeset/base/185514 Log: Fix a lock order reversal bug that could cause deadlock during fork(2). Reported by: kib Modified: head/lib/libc/stdlib/malloc.c Modified: head/lib/libc/stdlib/malloc.c ============================================================================== --- head/lib/libc/stdlib/malloc.c Mon Dec 1 10:16:25 2008 (r185513) +++ head/lib/libc/stdlib/malloc.c Mon Dec 1 10:20:59 2008 (r185514) @@ -5515,16 +5515,41 @@ _malloc_thread_cleanup(void) void _malloc_prefork(void) { - unsigned i; + bool again; + unsigned i, j; + arena_t *larenas[narenas], *tarenas[narenas]; /* Acquire all mutexes in a safe order. */ - malloc_spin_lock(&arenas_lock); - for (i = 0; i < narenas; i++) { - if (arenas[i] != NULL) - malloc_spin_lock(&arenas[i]->lock); - } - malloc_spin_unlock(&arenas_lock); + /* + * arenas_lock must be acquired after all of the arena mutexes, in + * order to avoid potential deadlock with arena_lock_balance[_hard](). + * Since arenas_lock protects the arenas array, the following code has + * to race with arenas_extend() callers until it succeeds in locking + * all arenas before locking arenas_lock. + */ + memset(larenas, 0, sizeof(arena_t *) * narenas); + do { + again = false; + + malloc_spin_lock(&arenas_lock); + for (i = 0; i < narenas; i++) { + if (arenas[i] != larenas[i]) { + memcpy(tarenas, arenas, sizeof(arena_t *) * + narenas); + malloc_spin_unlock(&arenas_lock); + for (j = 0; j < narenas; j++) { + if (larenas[j] != tarenas[j]) { + larenas[j] = tarenas[j]; + malloc_spin_lock( + &larenas[j]->lock); + } + } + again = true; + break; + } + } + } while (again); malloc_mutex_lock(&base_mtx); @@ -5539,6 +5564,7 @@ void _malloc_postfork(void) { unsigned i; + arena_t *larenas[narenas]; /* Release all mutexes, now that fork() has completed. */ @@ -5550,12 +5576,12 @@ _malloc_postfork(void) malloc_mutex_unlock(&base_mtx); - malloc_spin_lock(&arenas_lock); + memcpy(larenas, arenas, sizeof(arena_t *) * narenas); + malloc_spin_unlock(&arenas_lock); for (i = 0; i < narenas; i++) { - if (arenas[i] != NULL) - malloc_spin_unlock(&arenas[i]->lock); + if (larenas[i] != NULL) + malloc_spin_unlock(&larenas[i]->lock); } - malloc_spin_unlock(&arenas_lock); } /*