]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Fix blocking pthread_join. [BZ #23137]
authorStefan Liebler <stli@linux.vnet.ibm.com>
Thu, 17 May 2018 12:05:51 +0000 (14:05 +0200)
committerFlorian Weimer <fweimer@redhat.com>
Thu, 17 May 2018 12:05:51 +0000 (14:05 +0200)
On s390 (31bit) if glibc is build with -Os, pthread_join sometimes
blocks indefinitely. This is e.g. observable with
testcase intl/tst-gettext6.

pthread_join is calling lll_wait_tid(tid), which performs the futex-wait
syscall in a loop as long as tid != 0 (thread is alive).

On s390 (and build with -Os), tid is loaded from memory before
comparing against zero and then the tid is loaded a second time
in order to pass it to the futex-wait-syscall.
If the thread exits in between, then the futex-wait-syscall is
called with the value zero and it waits until a futex-wake occurs.
As the thread is already exited, there won't be a futex-wake.

In lll_wait_tid, the tid is stored to the local variable __tid,
which is then used as argument for the futex-wait-syscall.
But unfortunately the compiler is allowed to reload the value
from memory.

With this patch, the tid is loaded with atomic_load_acquire.
Then the compiler is not allowed to reload the value for __tid from memory.

ChangeLog:

[BZ #23137]
* sysdeps/nptl/lowlevellock.h (lll_wait_tid):
Use atomic_load_acquire to load __tid.

(cherry picked from commit 1660901840dfc9fde6c5720a32f901af6f08f00a)

ChangeLog
NEWS
sysdeps/nptl/lowlevellock.h

index dbae1b9270388c7ee93d8786d38c72e4a5647047..488bd789b8f86f0da2e08ae14d9bea3f9fb171f7 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2018-05-04  Stefan Liebler  <stli@linux.vnet.ibm.com>
+
+       [BZ #23137]
+       * sysdeps/nptl/lowlevellock.h (lll_wait_tid):
+       Use atomic_load_acquire to load __tid.
+
 2018-03-20  Joseph Myers  <joseph@codesourcery.com>
 
        [BZ #17343]
diff --git a/NEWS b/NEWS
index 7c1526004fea966d0edf291f7e6f2842573f7de1..8a2da5091f315ab9b50a242785524fc2cb8f081f 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -125,6 +125,7 @@ The following bugs are resolved with this release:
   [23005] resolv: Fix crash in resolver on memory allocation failure
   [23024] getlogin_r: return early when linux sentinel value is set
   [23037] resolv: Fully initialize struct mmsghdr in send_dg
+  [23137] s390: Fix blocking pthread_join
 \f
 Version 2.26
 
index 54e3c28b0b52db8d1d56bdaebc6feaed64d7537c..649aea813c15a822a8fa661674774ad31ce7cded 100644 (file)
@@ -181,11 +181,14 @@ extern int __lll_timedlock_wait (int *futex, const struct timespec *,
    thread ID while the clone is running and is reset to zero by the kernel
    afterwards.  The kernel up to version 3.16.3 does not use the private futex
    operations for futex wake-up when the clone terminates.  */
-#define lll_wait_tid(tid) \
-  do {                                 \
-    __typeof (tid) __tid;              \
-    while ((__tid = (tid)) != 0)       \
-      lll_futex_wait (&(tid), __tid, LLL_SHARED);\
+#define lll_wait_tid(tid)                              \
+  do {                                                 \
+    __typeof (tid) __tid;                              \
+    /* We need acquire MO here so that we synchronize  \
+       with the kernel's store to 0 when the clone     \
+       terminates. (see above)  */                     \
+    while ((__tid = atomic_load_acquire (&(tid))) != 0)        \
+      lll_futex_wait (&(tid), __tid, LLL_SHARED);      \
   } while (0)
 
 extern int __lll_timedwait_tid (int *, const struct timespec *)