From patchwork Fri Sep 17 12:40:11 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 45125 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id A67EA3857432 for ; Fri, 17 Sep 2021 12:42:22 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A67EA3857432 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1631882542; bh=36rPU96Hd2oi9gj1sIKQFg2rFzq3GgaAV6wlioSVZtg=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=SrJhxxQwKniWv6S0tFpxuuT0bSrBJYiZVf8u8roFOIeCzai3DatoDCNMAbkwK7a93 Q28pGM2ySykvg20A+4J1vKinfnBdkm/4xzAxNR2J39CDd5kOpYviVHytSKiSsfecL2 k0IMCJhx/ysbS2S+R3NFZx5LtYUaN+2PeZdSYYH8= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id 79D913857C47 for ; Fri, 17 Sep 2021 12:40:18 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 79D913857C47 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-164-KG_t8UNRNcm1Jlas-hSBiQ-1; Fri, 17 Sep 2021 08:40:15 -0400 X-MC-Unique: KG_t8UNRNcm1Jlas-hSBiQ-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id C1B991891EBD for ; Fri, 17 Sep 2021 12:40:14 +0000 (UTC) Received: from oldenburg.str.redhat.com (unknown [10.39.192.16]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 610EA1B5C2; Fri, 17 Sep 2021 12:40:13 +0000 (UTC) To: libc-alpha@sourceware.org Subject: [PATCH] nptl: pthread_kill needs to return ESRCH for old programs (bug 19193) Date: Fri, 17 Sep 2021 14:40:11 +0200 Message-ID: <87h7ejcr4k.fsf@oldenburg.str.redhat.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux) MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-12.7 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Florian Weimer via Libc-alpha From: Florian Weimer Reply-To: Florian Weimer Cc: Siddhesh Poyarekar Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" The fix for bug 19193 breaks some old applications which appear to use pthread_kill to probe if a thread is still running, something that is not supported by POSIX. --- Tested on i686-linux-gnu and x86_64-linux-gnu. I checked the test case and the second pthread_kill call is included in the disassembly. build-many-glibcs.py is still running. nptl/pthread_kill.c | 37 ++++++++++++++++++++++++------- sysdeps/pthread/tst-pthread_kill-exited.c | 21 ++++++++++++++++-- 2 files changed, 48 insertions(+), 10 deletions(-) diff --git a/nptl/pthread_kill.c b/nptl/pthread_kill.c index fb7862eff7..a44dc8f2d9 100644 --- a/nptl/pthread_kill.c +++ b/nptl/pthread_kill.c @@ -21,8 +21,11 @@ #include #include -int -__pthread_kill_internal (pthread_t threadid, int signo) +/* Sends SIGNO to THREADID. If the thread is about to exit or has + already exited on the kernel side, return NO_TID. Otherwise return + 0 or an error code. */ +static int +__pthread_kill_implementation (pthread_t threadid, int signo, int no_tid) { struct pthread *pd = (struct pthread *) threadid; if (pd == THREAD_SELF) @@ -52,11 +55,8 @@ __pthread_kill_internal (pthread_t threadid, int signo) signal is either not observable (the target thread has already blocked signals at this point), or it will fail, or it might be delivered to a new, unrelated thread that has reused the TID. - So do not actually send the signal. Do not report an error - because the threadid argument is still valid (the thread ID - lifetime has not ended), and ESRCH (for example) would be - misleading. */ - ret = 0; + So do not actually send the signal. */ + ret = no_tid; else { /* Using tgkill is a safety measure. pd->exit_lock ensures that @@ -71,6 +71,15 @@ __pthread_kill_internal (pthread_t threadid, int signo) return ret; } +int +__pthread_kill_internal (pthread_t threadid, int signo) +{ + /* Do not report an error in the no-tid case because the threadid + argument is still valid (the thread ID lifetime has not ended), + and ESRCH (for example) would be misleading. */ + return __pthread_kill_implementation (threadid, signo, 0); +} + int __pthread_kill (pthread_t threadid, int signo) { @@ -81,6 +90,7 @@ __pthread_kill (pthread_t threadid, int signo) return __pthread_kill_internal (threadid, signo); } + /* Some architectures (for instance arm) might pull raise through libgcc, so avoid the symbol version if it ends up being used on ld.so. */ #if !IS_IN(rtld) @@ -88,6 +98,17 @@ libc_hidden_def (__pthread_kill) versioned_symbol (libc, __pthread_kill, pthread_kill, GLIBC_2_34); # if OTHER_SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_34) -compat_symbol (libc, __pthread_kill, pthread_kill, GLIBC_2_0); +/* Variant which returns ESRCH in the no-TID case, for backwards + compatibility. */ +int +attribute_compat_text_section +__pthread_kill_esrch (pthread_t threadid, int signo) +{ + if (__is_internal_signal (signo)) + return EINVAL; + + return __pthread_kill_implementation (threadid, signo, ESRCH); +} +compat_symbol (libc, __pthread_kill_esrch, pthread_kill, GLIBC_2_0); # endif #endif diff --git a/sysdeps/pthread/tst-pthread_kill-exited.c b/sysdeps/pthread/tst-pthread_kill-exited.c index 7575fb6d58..bcb7253f7e 100644 --- a/sysdeps/pthread/tst-pthread_kill-exited.c +++ b/sysdeps/pthread/tst-pthread_kill-exited.c @@ -16,11 +16,15 @@ License along with the GNU C Library; if not, see . */ -/* This test verifies that pthread_kill returns 0 (and not ESRCH) for - a thread that has exited on the kernel side. */ +/* This test verifies that the default pthread_kill returns 0 (and not + ESRCH) for a thread that has exited on the kernel side. */ +#include +#include +#include #include #include +#include #include #include @@ -30,6 +34,12 @@ noop_thread (void *closure) return NULL; } +#if TEST_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_34) +extern __typeof (pthread_kill) compat_pthread_kill; +compat_symbol_reference (libpthread, compat_pthread_kill, pthread_kill, + GLIBC_2_0); +#endif + static int do_test (void) { @@ -37,7 +47,14 @@ do_test (void) support_wait_for_thread_exit (); + /* NB: Always uses the default symbol due to separate compilation. */ xpthread_kill (thr, SIGUSR1); + +#if TEST_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_34) + /* Old binaries need the non-conforming ESRCH error code. */ + TEST_COMPARE (compat_pthread_kill (thr, SIGUSR1), ESRCH); +#endif + xpthread_join (thr); return 0;