summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorPaul Irofti <pirofti@cvs.openbsd.org>2018-04-24 16:28:43 +0000
committerPaul Irofti <pirofti@cvs.openbsd.org>2018-04-24 16:28:43 +0000
commit42d8ef263eb22249f62ae63279fdc3c85980a0e8 (patch)
treec5ebaa7506e978533dd69ab567615a053fbaef01 /lib
parent4fb053a8d5cca51b3ebdf34a236bd5320909952f (diff)
Validate timespec and return ECANCELED when interrupted with SA_RESTART.
Discussing with mpi@ and guenther@, we decided to first fix the existing semaphore implementation with regards to SA_RESTART and POSIX compliant returns in the case where we deal with restartable signals. Currently we return EINTR everywhere which is mostly incorrect as the user can not know if she needs to recall the syscall or not. Return ECANCELED to signal that SA_RESTART was set and EINTR otherwise. Regression tests pass and so does the posixsuite. Timespec validation bits are needed to pass the later. OK mpi@, guenther@
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/sys/__thrsleep.214
-rw-r--r--lib/libc/thread/rthread_sync.c8
-rw-r--r--lib/libpthread/man/sem_wait.319
-rw-r--r--lib/librthread/rthread_rwlock.c10
-rw-r--r--lib/librthread/rthread_sem.c15
5 files changed, 46 insertions, 20 deletions
diff --git a/lib/libc/sys/__thrsleep.2 b/lib/libc/sys/__thrsleep.2
index 2566d043fab..28dc4483688 100644
--- a/lib/libc/sys/__thrsleep.2
+++ b/lib/libc/sys/__thrsleep.2
@@ -1,4 +1,4 @@
-.\" $OpenBSD: __thrsleep.2,v 1.6 2016/09/03 17:02:22 akfaew Exp $
+.\" $OpenBSD: __thrsleep.2,v 1.7 2018/04/24 16:28:42 pirofti Exp $
.\"
.\" Copyright (c) 2012 Philip Guenther <guenther@openbsd.org>
.\"
@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: September 3 2016 $
+.Dd $Mdocdate: April 24 2018 $
.Dt __THRSLEEP 2
.Os
.Sh NAME
@@ -148,12 +148,19 @@ arguments was reached.
A signal arrived or the
.Fa abort
argument pointed to a non-zero value.
+.It Bq Er ECANCELED
+A signal arrived and
+.Fa SA_RESTART
+was set.
.It Bq Er EINVAL
The
.Fa clock_id
argument is not a valid
.Xr clock_gettime 2
-clock id.
+clock id
+or
+.Fa abstime
+specified a nanosecond value less than zero or greater than 1000 million.
.El
.Pp
.Fn __thrwakeup
@@ -167,6 +174,7 @@ with the same
were found.
.El
.Sh SEE ALSO
+.Xr sigaction 2 ,
.Xr pthread_cond_wait 3 ,
.Xr pthread_mutex_lock 3 ,
.Xr tsleep 9
diff --git a/lib/libc/thread/rthread_sync.c b/lib/libc/thread/rthread_sync.c
index 91ce55cbcf9..42e1a7ee737 100644
--- a/lib/libc/thread/rthread_sync.c
+++ b/lib/libc/thread/rthread_sync.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rthread_sync.c,v 1.4 2017/09/05 02:40:54 guenther Exp $ */
+/* $OpenBSD: rthread_sync.c,v 1.5 2018/04/24 16:28:42 pirofti Exp $ */
/*
* Copyright (c) 2004,2005 Ted Unangst <tedu@openbsd.org>
* Copyright (c) 2012 Philip Guenther <guenther@openbsd.org>
@@ -375,7 +375,8 @@ pthread_cond_timedwait(pthread_cond_t *condp, pthread_mutex_t *mutexp,
* cancellation) then we should just go back to
* sleep without changing state (timeouts, etc).
*/
- if (error == EINTR && (tib->tib_canceled == 0 ||
+ if ((error == EINTR || error == ECANCELED) &&
+ (tib->tib_canceled == 0 ||
(tib->tib_cantcancel & CANCEL_DISABLED))) {
_spinlock(&mutex->lock);
continue;
@@ -514,7 +515,8 @@ pthread_cond_wait(pthread_cond_t *condp, pthread_mutex_t *mutexp)
* cancellation) then we should just go back to
* sleep without changing state (timeouts, etc).
*/
- if (error == EINTR && (tib->tib_canceled == 0 ||
+ if ((error == EINTR || error == ECANCELED) &&
+ (tib->tib_canceled == 0 ||
(tib->tib_cantcancel & CANCEL_DISABLED))) {
_spinlock(&mutex->lock);
continue;
diff --git a/lib/libpthread/man/sem_wait.3 b/lib/libpthread/man/sem_wait.3
index 31c091eda89..1d91acf16d9 100644
--- a/lib/libpthread/man/sem_wait.3
+++ b/lib/libpthread/man/sem_wait.3
@@ -1,4 +1,4 @@
-.\" $OpenBSD: sem_wait.3,v 1.9 2013/06/05 03:44:50 tedu Exp $
+.\" $OpenBSD: sem_wait.3,v 1.10 2018/04/24 16:28:42 pirofti Exp $
.\"
.\" Copyright (C) 2000 Jason Evans <jasone@FreeBSD.org>.
.\" All rights reserved.
@@ -28,7 +28,7 @@
.\" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $FreeBSD: src/lib/libc_r/man/sem_wait.3,v 1.8 2001/10/01 16:09:09 ru Exp $
-.Dd $Mdocdate: June 5 2013 $
+.Dd $Mdocdate: April 24 2018 $
.Dt SEM_WAIT 3
.Os
.Sh NAME
@@ -86,9 +86,24 @@ points to an invalid semaphore.
.El
.Pp
Additionally,
+.Fn sem_wait
+and
+.Fn sem_timedwait
+will fail if:
+.Bl -tag -width Er
+.It Bq Er EINTR
+The call was interrupted by a signal.
+.El
+.Pp
+Additionally,
.Fn sem_timedwait
will fail if:
.Bl -tag -width Er
+.It Bq Er EINVAL
+.Fa abstime
+was
+.Dv NULL
+or specified a nanosecond value less than zero or greater than 1000 million.
.It Bq Er ETIMEDOUT
The semaphore value was zero and could not be decremented before
.Fa abstime
diff --git a/lib/librthread/rthread_rwlock.c b/lib/librthread/rthread_rwlock.c
index a75e88c52e4..0ca1d702953 100644
--- a/lib/librthread/rthread_rwlock.c
+++ b/lib/librthread/rthread_rwlock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rthread_rwlock.c,v 1.10 2017/07/29 16:42:10 deraadt Exp $ */
+/* $OpenBSD: rthread_rwlock.c,v 1.11 2018/04/24 16:28:42 pirofti Exp $ */
/*
* Copyright (c) 2004,2005 Ted Unangst <tedu@openbsd.org>
* Copyright (c) 2012 Philip Guenther <guenther@openbsd.org>
@@ -143,8 +143,8 @@ int
pthread_rwlock_timedrdlock(pthread_rwlock_t *lockp,
const struct timespec *abstime)
{
- if (abstime == NULL || abstime->tv_sec < 0 || abstime->tv_nsec < 0 ||
- abstime->tv_nsec > 1000000000)
+ if (abstime == NULL || abstime->tv_nsec < 0 ||
+ abstime->tv_nsec >= 1000000000)
return (EINVAL);
return (_rthread_rwlock_rdlock(lockp, abstime, 0));
}
@@ -210,8 +210,8 @@ int
pthread_rwlock_timedwrlock(pthread_rwlock_t *lockp,
const struct timespec *abstime)
{
- if (abstime == NULL || abstime->tv_sec < 0 || abstime->tv_nsec < 0 ||
- abstime->tv_nsec > 1000000000)
+ if (abstime == NULL || abstime->tv_nsec < 0 ||
+ abstime->tv_nsec >= 1000000000)
return (EINVAL);
return (_rthread_rwlock_wrlock(lockp, abstime, 0));
}
diff --git a/lib/librthread/rthread_sem.c b/lib/librthread/rthread_sem.c
index 196fb8ec357..daabe98af3f 100644
--- a/lib/librthread/rthread_sem.c
+++ b/lib/librthread/rthread_sem.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rthread_sem.c,v 1.26 2017/09/05 02:40:54 guenther Exp $ */
+/* $OpenBSD: rthread_sem.c,v 1.27 2018/04/24 16:28:42 pirofti Exp $ */
/*
* Copyright (c) 2004,2005,2013 Ted Unangst <tedu@openbsd.org>
* All Rights Reserved.
@@ -75,7 +75,7 @@ _sem_wait(sem_t sem, int tryonly, const struct timespec *abstime,
&sem->lock, delayed_cancel);
_spinlock(&sem->lock);
/* ignore interruptions other than cancelation */
- if (r == EINTR && (delayed_cancel == NULL ||
+ if (r == ECANCELED && (delayed_cancel == NULL ||
*delayed_cancel == 0))
r = 0;
} while (r == 0 && sem->value == 0);
@@ -268,15 +268,16 @@ sem_timedwait(sem_t *semp, const struct timespec *abstime)
int r;
PREP_CANCEL_POINT(tib);
- if (!_threads_ready)
- _rthread_init();
- self = tib->tib_thread;
-
- if (!semp || !(sem = *semp)) {
+ if (!semp || !(sem = *semp) || abstime == NULL ||
+ abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) {
errno = EINVAL;
return (-1);
}
+ if (!_threads_ready)
+ _rthread_init();
+ self = tib->tib_thread;
+
ENTER_DELAYED_CANCEL_POINT(tib, self);
r = _sem_wait(sem, 0, abstime, &self->delayed_cancel);
LEAVE_CANCEL_POINT_INNER(tib, r);