From e0ad4b33be27625a6d90fe45e3344ce322784cf9 Mon Sep 17 00:00:00 2001 From: guenther Date: Sun, 10 May 2015 18:33:15 +0000 Subject: [PATCH] In the child after fork, the dl lock has to be forced as its inner spinlock may have been grabbed by another thread in the parent before the fork problem report from dcoppa@, ok kettenis@ --- lib/librthread/rthread.c | 15 +++++++++------ lib/librthread/rthread_fork.c | 14 +++++++++----- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/lib/librthread/rthread.c b/lib/librthread/rthread.c index 72babbf5032..5f9ca87471c 100644 --- a/lib/librthread/rthread.c +++ b/lib/librthread/rthread.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rthread.c,v 1.81 2015/04/29 06:01:37 guenther Exp $ */ +/* $OpenBSD: rthread.c,v 1.82 2015/05/10 18:33:15 guenther Exp $ */ /* * Copyright (c) 2004,2005 Ted Unangst * All Rights Reserved. @@ -671,8 +671,7 @@ _rthread_dl_lock(int what) static struct pthread_queue lockers = TAILQ_HEAD_INITIALIZER(lockers); static int count = 0; - if (what == 0) - { + if (what == 0) { pthread_t self = pthread_self(); /* lock, possibly recursive */ @@ -689,9 +688,7 @@ _rthread_dl_lock(int what) } count++; _spinunlock(&lock); - } - else - { + } else if (what == 1) { /* unlock, possibly recursive */ if (--count == 0) { pthread_t next; @@ -704,6 +701,12 @@ _rthread_dl_lock(int what) if (next != NULL) __thrwakeup(next, 1); } + } else { + /* reinit: used in child after fork to clear the queue */ + lock = _SPINLOCK_UNLOCKED_ASSIGN; + if (--count == 0) + owner = NULL; + TAILQ_INIT(&lockers); } } diff --git a/lib/librthread/rthread_fork.c b/lib/librthread/rthread_fork.c index c9086daf595..7bca5b0595f 100644 --- a/lib/librthread/rthread_fork.c +++ b/lib/librthread/rthread_fork.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rthread_fork.c,v 1.11 2015/04/07 01:27:07 guenther Exp $ */ +/* $OpenBSD: rthread_fork.c,v 1.12 2015/05/10 18:33:15 guenther Exp $ */ /* * Copyright (c) 2008 Kurt Miller @@ -105,12 +105,12 @@ _dofork(int is_vfork) _thread_malloc_unlock(); _thread_atexit_unlock(); + if (newid == 0) { #if defined(__ELF__) - if (_DYNAMIC) - _rthread_dl_lock(1); + /* reinitialize the lock in the child */ + if (_DYNAMIC) + _rthread_dl_lock(2); #endif - - if (newid == 0) { /* update this thread's structure */ me->tid = getthrid(); me->donesem.lock = _SPINLOCK_UNLOCKED_ASSIGN; @@ -128,6 +128,10 @@ _dofork(int is_vfork) /* single threaded now */ __isthreaded = 0; } +#if defined(__ELF__) + else if (_DYNAMIC) + _rthread_dl_lock(1); +#endif return newid; } -- 2.20.1