summaryrefslogtreecommitdiff
path: root/lib/libc/thread
diff options
context:
space:
mode:
authorPhilip Guenther <guenther@cvs.openbsd.org>2017-10-28 21:25:25 +0000
committerPhilip Guenther <guenther@cvs.openbsd.org>2017-10-28 21:25:25 +0000
commit7c90e1a78a1b6a1d524aa57c159d08a51ef9df17 (patch)
tree8f7a19431e305aff3d73e7c9300c2accaf294e87 /lib/libc/thread
parent2717495d33a63467db8130f749e61927d7efafb9 (diff)
If the init_routine used with pthread_once() is canceled, then we need to
unlock the mutex inside the pthread_once_t. Push a cleanup wrapper for that. Diff from Scott Cheloha <scottcheloha@gmail.com> ok mpi@
Diffstat (limited to 'lib/libc/thread')
-rw-r--r--lib/libc/thread/rthread_once.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/lib/libc/thread/rthread_once.c b/lib/libc/thread/rthread_once.c
index b8c6ba79161..014532e56c4 100644
--- a/lib/libc/thread/rthread_once.c
+++ b/lib/libc/thread/rthread_once.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rthread_once.c,v 1.1 2017/08/15 06:13:24 guenther Exp $ */
+/* $OpenBSD: rthread_once.c,v 1.2 2017/10/28 21:25:24 guenther Exp $ */
/*
* Copyright (c) 2004,2005 Ted Unangst <tedu@openbsd.org>
* All Rights Reserved.
@@ -17,13 +17,23 @@
*/
#include <pthread.h>
+#include <stdlib.h>
+
+static void
+mutex_unlock(void *arg)
+{
+ if (pthread_mutex_unlock(arg))
+ abort();
+}
int
pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
{
pthread_mutex_lock(&once_control->mutex);
if (once_control->state == PTHREAD_NEEDS_INIT) {
+ pthread_cleanup_push(mutex_unlock, &once_control->mutex);
init_routine();
+ pthread_cleanup_pop(0);
once_control->state = PTHREAD_DONE_INIT;
}
pthread_mutex_unlock(&once_control->mutex);