diff options
author | barts <none@none> | 2007-05-16 16:56:20 -0700 |
---|---|---|
committer | barts <none@none> | 2007-05-16 16:56:20 -0700 |
commit | d02b2ecc45d7aceb5456026da8da5fbe6402d17b (patch) | |
tree | 881e164b8173dcb1faeee309a8fb0c5aa8c6cfcf /usr/src/lib/libumem/common/umem_update_thread.c | |
parent | 05456eff3158ab7350d7ff8891ed6bf0030fc33b (diff) | |
download | illumos-gate-d02b2ecc45d7aceb5456026da8da5fbe6402d17b.tar.gz |
6533110 fork/umem deadlock causes svc.startd to hang
Diffstat (limited to 'usr/src/lib/libumem/common/umem_update_thread.c')
-rw-r--r-- | usr/src/lib/libumem/common/umem_update_thread.c | 39 |
1 files changed, 31 insertions, 8 deletions
diff --git a/usr/src/lib/libumem/common/umem_update_thread.c b/usr/src/lib/libumem/common/umem_update_thread.c index e6edd07c6d..952cb56324 100644 --- a/usr/src/lib/libumem/common/umem_update_thread.c +++ b/usr/src/lib/libumem/common/umem_update_thread.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -114,13 +113,13 @@ umem_update_thread(void *arg) &umem_update_lock, &abs_time); } } - /* LINTED no return statement */ } int umem_create_update_thread(void) { sigset_t sigmask, oldmask; + thread_t newthread; ASSERT(MUTEX_HELD(&umem_update_lock)); ASSERT(umem_update_thr == 0); @@ -130,12 +129,36 @@ umem_create_update_thread(void) */ (void) sigfillset(&sigmask); (void) thr_sigsetmask(SIG_BLOCK, &sigmask, &oldmask); + + /* + * drop the umem_update_lock; we cannot hold locks acquired in + * pre-fork handler while calling thr_create or thr_continue(). + */ + + (void) mutex_unlock(&umem_update_lock); + if (thr_create(NULL, NULL, umem_update_thread, NULL, - THR_BOUND | THR_DAEMON | THR_DETACHED, &umem_update_thr) == 0) { + THR_BOUND | THR_DAEMON | THR_DETACHED | THR_SUSPENDED, + &newthread) == 0) { (void) thr_sigsetmask(SIG_SETMASK, &oldmask, NULL); + + (void) mutex_lock(&umem_update_lock); + /* + * due to the locking in umem_reap(), only one thread can + * ever call umem_create_update_thread() at a time. This + * must be the case for this code to work. + */ + + ASSERT(umem_update_thr == 0); + umem_update_thr = newthread; + (void) mutex_unlock(&umem_update_lock); + (void) thr_continue(newthread); + (void) mutex_lock(&umem_update_lock); + return (1); + } else { /* thr_create failed */ + (void) thr_sigsetmask(SIG_SETMASK, &oldmask, NULL); + (void) mutex_lock(&umem_update_lock); } - umem_update_thr = 0; - (void) thr_sigsetmask(SIG_SETMASK, &oldmask, NULL); return (0); } |