diff options
| author | ad <ad@NetBSD.org> | 2020-01-25 18:01:28 +0000 |
|---|---|---|
| committer | ad <ad@NetBSD.org> | 2020-01-25 18:01:28 +0000 |
| commit | 496256f073ef40780955ff0da5ee4d1385c52d11 (patch) | |
| tree | 92b541881c5fa4c36db9f39c5b41bfea4c1ed767 /lib/libpthread/pthread.c | |
| parent | 5b40ee73af04033a686b0e956c88865251ed5320 (diff) | |
pthread_exit(): it looks there there is at least one path through which
a thread can exit with waiters still hanging off it (cancellation when
waiting on a condvar) so deal with all/any crappy failure like that and
make sure there are never any waiters left before exiting. Maybe of help
for:
PR: bin/50350: rump/rumpkern/t_sp/stress_{long,short} fail on Core 2
Diffstat (limited to 'lib/libpthread/pthread.c')
| -rw-r--r-- | lib/libpthread/pthread.c | 28 |
1 files changed, 25 insertions, 3 deletions
diff --git a/lib/libpthread/pthread.c b/lib/libpthread/pthread.c index 41c9305572f..90b497cf08d 100644 --- a/lib/libpthread/pthread.c +++ b/lib/libpthread/pthread.c @@ -1,4 +1,4 @@ -/* $NetBSD: pthread.c,v 1.155 2020/01/25 15:41:52 ad Exp $ */ +/* $NetBSD: pthread.c,v 1.156 2020/01/25 18:01:28 ad Exp $ */ /*- * Copyright (c) 2001, 2002, 2003, 2006, 2007, 2008, 2020 @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: pthread.c,v 1.155 2020/01/25 15:41:52 ad Exp $"); +__RCSID("$NetBSD: pthread.c,v 1.156 2020/01/25 18:01:28 ad Exp $"); #define __EXPOSE_STACK 1 @@ -621,6 +621,23 @@ pthread_resume_np(pthread_t thread) return errno; } +/* + * In case the thread is exiting at an inopportune time leaving waiters not + * awoken (because cancelled, for instance) make sure we have no waiters + * left. + */ +static void +pthread__clear_waiters(pthread_t self) +{ + + if (self->pt_nwaiters != 0) { + (void)_lwp_unpark_all(self->pt_waiters, self->pt_nwaiters, + NULL); + self->pt_nwaiters = 0; + } + self->pt_willpark = 0; +} + void pthread_exit(void *retval) { @@ -658,7 +675,10 @@ pthread_exit(void *retval) /* Perform cleanup of thread-specific data */ pthread__destroy_tsd(self); - /* Signal our exit. */ + /* + * Signal our exit. Our stack and pthread_t won't be reused until + * pthread_create() can see from kernel info that this LWP is gone. + */ self->pt_exitval = retval; if (self->pt_flags & PT_FLAG_DETACHED) { self->pt_state = PT_STATE_DEAD; @@ -670,11 +690,13 @@ pthread_exit(void *retval) pthread_mutex_lock(&pthread__deadqueue_lock); PTQ_INSERT_TAIL(&pthread__deadqueue, self, pt_deadq); pthread_mutex_unlock(&pthread__deadqueue_lock); + pthread__clear_waiters(self); _lwp_exit(); } else { self->pt_state = PT_STATE_ZOMBIE; pthread_cond_broadcast(&self->pt_joiners); pthread_mutex_unlock(&self->pt_lock); + pthread__clear_waiters(self); /* Note: name will be freed by the joiner. */ _lwp_exit(); } |
