Index | Thread | Search

From:
Scott Cheloha <scottcheloha@gmail.com>
Subject:
pthread_mutex_timedlock(3): don't block forever if the timeout is NULL
To:
tech@openbsd.org
Date:
Tue, 9 Jan 2024 23:14:08 -0600

Download raw body.

Thread
Both pthread_mutex_timedlock(3) implementations pass the timeout
parameter from the caller through to the internal implementation
function.  In both of those functions, a NULL timeout pointer means
"no timeout" or "block indefinitely".

So, we have accidentally extended the pthread_mutex_timedlock(3)
specification with special, undocumented behavior when the timeout
pointer is NULL.

The easy fix is to copy the timeout to the stack before passing it on.

This change will cause any code that depends upon the current behavior
to segfault instead of blocking indefinitely.  I think it's unlikely
such code exists.  It it does exist, it is not portable.

ok?

Index: rthread_mutex.c
===================================================================
RCS file: /cvs/src/lib/libc/thread/rthread_mutex.c,v
diff -u -p -r1.5 rthread_mutex.c
--- rthread_mutex.c	13 Feb 2019 13:09:32 -0000	1.5
+++ rthread_mutex.c	10 Jan 2024 04:44:57 -0000
@@ -211,9 +211,11 @@ pthread_mutex_trylock(pthread_mutex_t *m
 }
 
 int
-pthread_mutex_timedlock(pthread_mutex_t *mutexp, const struct timespec *abs)
+pthread_mutex_timedlock(pthread_mutex_t *mutexp, const struct timespec *absp)
 {
-	return (_rthread_mutex_timedlock(mutexp, 0, abs, 1));
+	struct timespec abs = *absp;
+
+	return (_rthread_mutex_timedlock(mutexp, 0, &abs, 1));
 }
 
 int
Index: rthread_sync.c
===================================================================
RCS file: /cvs/src/lib/libc/thread/rthread_sync.c,v
diff -u -p -r1.6 rthread_sync.c
--- rthread_sync.c	10 Jan 2024 04:28:43 -0000	1.6
+++ rthread_sync.c	10 Jan 2024 04:44:57 -0000
@@ -179,9 +179,11 @@ pthread_mutex_trylock(pthread_mutex_t *p
 }
 
 int
-pthread_mutex_timedlock(pthread_mutex_t *p, const struct timespec *abstime)
+pthread_mutex_timedlock(pthread_mutex_t *p, const struct timespec *abstimep)
 {
-	return (_rthread_mutex_lock(p, 0, abstime));
+	struct timespec abstime = *abstimep;
+
+	return (_rthread_mutex_lock(p, 0, &abstime));
 }
 
 int