From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 66987 invoked by alias); 11 May 2018 10:35:10 -0000 Mailing-List: contact libc-stable-help@sourceware.org; run by ezmlm Precedence: bulk List-Post: List-Help: List-Subscribe: List-Archive: Sender: libc-stable-owner@sourceware.org Received: (qmail 66966 invoked by uid 89); 11 May 2018 10:35:09 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Checked: by ClamAV 0.99.4 on sourceware.org X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.4 required=5.0 tests=AWL,BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,SPF_PASS,URIBL_RED autolearn=ham version=3.3.2 spammy= X-Spam-Status: No, score=-25.4 required=5.0 tests=AWL,BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,SPF_PASS,URIBL_RED autolearn=ham version=3.3.2 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on sourceware.org X-Spam-Level: X-HELO: vmicros1.altlinux.org Received: from vmicros1.altlinux.org (HELO vmicros1.altlinux.org) (194.107.17.57) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 11 May 2018 10:35:08 +0000 Received: from mua.local.altlinux.org (mua.local.altlinux.org [192.168.1.14]) by vmicros1.altlinux.org (Postfix) with ESMTP id 929BE72CA57 for ; Fri, 11 May 2018 13:35:06 +0300 (MSK) Received: by mua.local.altlinux.org (Postfix, from userid 508) id 82D047CC687; Fri, 11 May 2018 13:35:06 +0300 (MSK) Date: Mon, 01 Jan 2018 00:00:00 -0000 From: "Dmitry V. Levin" To: libc-stable@sourceware.org Subject: [2.27 COMMITTED] Fix blocking pthread_join. [BZ #23137] Message-ID: <20180511103506.GI31430@altlinux.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline X-IsSubscribed: yes X-SW-Source: 2018-05/txt/msg00009.txt.bz2 From: Stefan Liebler 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 | 6 ++++++ sysdeps/nptl/lowlevellock.h | 13 ++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index fce0575..ca6b3ea 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2018-05-04 Stefan Liebler + + [BZ #23137] + * sysdeps/nptl/lowlevellock.h (lll_wait_tid): + Use atomic_load_acquire to load __tid. + 2018-04-24 Joseph Myers * sysdeps/unix/sysv/linux/sys/ptrace.h diff --git a/sysdeps/nptl/lowlevellock.h b/sysdeps/nptl/lowlevellock.h index 8326e28..bfbda99 100644 --- a/sysdeps/nptl/lowlevellock.h +++ b/sysdeps/nptl/lowlevellock.h @@ -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 *) -- ldv