Save and restore errno around FUTEX_WAIT futex(2) operations. While there
authorkettenis <kettenis@openbsd.org>
Sun, 13 Jun 2021 21:11:54 +0000 (21:11 +0000)
committerkettenis <kettenis@openbsd.org>
Sun, 13 Jun 2021 21:11:54 +0000 (21:11 +0000)
remove the unused _wait() function in librthread such that we don't have to
add the save/restore sequence there.

Fixed building Python as a race with another thread unlocking a futex(2)
would make futex(2) set errno to EAGAIN which would confuse Python in
beleiving that readdir(2) failed instead of reaching the end of the
directory.

Spotted and tested by tb@
ok bluhm@

lib/libc/thread/synch.h
lib/librthread/synch.h

index 91b5001..6b9fab1 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: synch.h,v 1.6 2021/05/21 16:52:42 kettenis Exp $ */
+/*     $OpenBSD: synch.h,v 1.7 2021/06/13 21:11:54 kettenis Exp $ */
 /*
  * Copyright (c) 2017 Martin Pieuchot
  *
@@ -29,12 +29,15 @@ static inline int
 _twait(volatile uint32_t *p, int val, clockid_t clockid, const struct timespec *abs)
 {
        struct timespec rel;
+       int saved_errno = errno;
        int error;
 
        if (abs == NULL) {
                error = futex(p, FUTEX_WAIT_PRIVATE, val, NULL, NULL);
-               if (error == -1)
+               if (error == -1) {
                        error = errno;
+                       errno = saved_errno;
+               }
                return error;
        }
 
@@ -50,8 +53,10 @@ _twait(volatile uint32_t *p, int val, clockid_t clockid, const struct timespec *
                return ETIMEDOUT;
 
        error = futex(p, FUTEX_WAIT_PRIVATE, val, &rel, NULL);
-       if (error == -1)
+       if (error == -1) {
                error = errno;
+               errno = saved_errno;
+       }
        return error;
 }
 
index e5c623e..e6ad156 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: synch.h,v 1.7 2021/05/21 16:52:42 kettenis Exp $ */
+/*     $OpenBSD: synch.h,v 1.8 2021/06/13 21:11:54 kettenis Exp $ */
 /*
  * Copyright (c) 2017 Martin Pieuchot
  *
@@ -25,23 +25,19 @@ _wake(volatile uint32_t *p, int n)
        return futex(p, FUTEX_WAKE, n, NULL, NULL);
 }
 
-static inline void
-_wait(volatile uint32_t *p, int val)
-{
-       while (*p != (uint32_t)val)
-               futex(p, FUTEX_WAIT, val, NULL, NULL);
-}
-
 static inline int
 _twait(volatile uint32_t *p, int val, clockid_t clockid, const struct timespec *abs)
 {
        struct timespec rel;
+       int saved_errno = errno;
        int error;
 
        if (abs == NULL) {
                error = futex(p, FUTEX_WAIT, val, NULL, NULL);
-               if (error == -1)
+               if (error == -1) {
                        error = errno;
+                       errno = saved_errno;
+               }
                return error;
        }
 
@@ -57,8 +53,10 @@ _twait(volatile uint32_t *p, int val, clockid_t clockid, const struct timespec *
                return ETIMEDOUT;
 
        error = futex(p, FUTEX_WAIT, val, &rel, NULL);
-       if (error == -1)
+       if (error == -1) {
                error = errno;
+               errno = saved_errno;
+       }
        return error;
 }