From patchwork Mon May 3 21:00:01 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 43238 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 F04F43957413; Mon, 3 May 2021 21:00:15 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org F04F43957413 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1620075616; bh=tEdH7x1qAyEGypnS0tKN+2tPi+tCqd1R0CJYBYL+t4A=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=RfuvwsptHl0eexsiCO79M7B7j9slLjkdwUdOCpDiqOlYPR68oi8Vb6j9rIGk+mpiJ xCz+Lfc2lIgfxlT/yG6wPvrBR5xG5Ah1OQwk/EQVs19xOrd4XsVjR98iiZBatoLf6S Sqky1BoXnXISQOaecXgngx/vjRMa9mABYA55gNUc= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-qk1-x72e.google.com (mail-qk1-x72e.google.com [IPv6:2607:f8b0:4864:20::72e]) by sourceware.org (Postfix) with ESMTPS id 8941A3950406 for ; Mon, 3 May 2021 21:00:12 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 8941A3950406 Received: by mail-qk1-x72e.google.com with SMTP id a2so6547495qkh.11 for ; Mon, 03 May 2021 14:00:12 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=tEdH7x1qAyEGypnS0tKN+2tPi+tCqd1R0CJYBYL+t4A=; b=fGONomoN1kZe0e+IANMurmMeSAC6rR/QAXT7ZZ8SY/EyC/BTYNTIgOHANZj44U7hV0 9ykLHqWBdveXoYOMuweH4jrw2Ax9ibJrVmKl/cqv1k53YAS5FEdJjmKmtbeu7F0SLwpV 3gLK4KyoN9+++FEQTbdy49rJSe+srN3x1a2tYPpTANAW1YpOi8oCg2JDkSW1tajIZdqs Jwq6A8grg8dpAea319loy8J9igL0K0lCl1TqDNPC6Yi9DmoMKGKoLtfLJZ+EnKc+icTY jNmwDjawvk+X3NyzC/nWPyTj2g7XdKUXp1INsFVqaMmdyaKA99bWfvYR49maqvnnooX/ gh6Q== X-Gm-Message-State: AOAM532qSjwDiyJWs+9ywok4fHabVskJLpSbmyzIWyfFO9LauqAC29P+ qwqhkeWo7OL2ww/GttpS4P1gaL33ZPn2KQ== X-Google-Smtp-Source: ABdhPJxL5PoDdxmwE+HSkWsxRfclas1D96OfoIWC5/jMu0H98L2SFRueEwYAehrumF9NliFXozVjog== X-Received: by 2002:a37:46c5:: with SMTP id t188mr21901871qka.47.1620075611732; Mon, 03 May 2021 14:00:11 -0700 (PDT) Received: from birita.. ([177.194.41.149]) by smtp.googlemail.com with ESMTPSA id w196sm4578090qkb.90.2021.05.03.14.00.10 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 03 May 2021 14:00:11 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH v3 2/6] nptl: Implement raise in terms of pthread_kill Date: Mon, 3 May 2021 18:00:01 -0300 Message-Id: <20210503210005.2891859-2-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210503210005.2891859-1-adhemerval.zanella@linaro.org> References: <20210503210005.2891859-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-11.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, URIBL_BLACK autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) 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: Adhemerval Zanella via Libc-alpha From: Adhemerval Zanella Netto Reply-To: Adhemerval Zanella Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" Changes from v2: * Rebase against master. * Do not added the versioned symbol for rtld. Changes from v1: * Handle vfork usage for raise and obtain the TID using a syscall instead of reading from TCB. --- Now that pthread_kill is provided by libc.so and async-signal-safe, it is possible to implement the generic POSIX implementation as pthread_kill(pthread_self(), sig). For Linux implementation, pthread_kill read the targetting TID from the TCB. For raise, this it not possible because it would make raise fail when issue after vfork (where creates the resulting process has a different TID from the parent, but its TCB is not updated as for pthread_create). For this case, gettid is called directly. Checked on x86_64-linux-gnu. --- include/pthread.h | 5 ++++ nptl/pthreadP.h | 4 +-- nptl/pthread_kill.c | 42 +++++++++++++++----------- nptl/pthread_self.c | 4 ++- sysdeps/htl/pthreadP.h | 2 -- sysdeps/posix/raise.c | 11 +++++-- sysdeps/unix/sysv/linux/raise.c | 52 --------------------------------- 7 files changed, 44 insertions(+), 76 deletions(-) delete mode 100644 sysdeps/unix/sysv/linux/raise.c diff --git a/include/pthread.h b/include/pthread.h index 858c869a16..2623fb5e95 100644 --- a/include/pthread.h +++ b/include/pthread.h @@ -13,4 +13,9 @@ extern int __pthread_barrier_wait (pthread_barrier_t *__barrier) /* This function is called to initialize the pthread library. */ extern void __pthread_initialize (void) __attribute__ ((weak)); + +extern int __pthread_kill (pthread_t threadid, int signo); + +extern pthread_t __pthread_self (void); + #endif diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h index 00d2cfe764..3e5aba74ed 100644 --- a/nptl/pthreadP.h +++ b/nptl/pthreadP.h @@ -559,11 +559,11 @@ extern int __pthread_once (pthread_once_t *once_control, libc_hidden_proto (__pthread_once) extern int __pthread_atfork (void (*prepare) (void), void (*parent) (void), void (*child) (void)); -extern pthread_t __pthread_self (void); +libc_hidden_proto (__pthread_self) extern int __pthread_equal (pthread_t thread1, pthread_t thread2); extern int __pthread_detach (pthread_t th); extern int __pthread_cancel (pthread_t th); -extern int __pthread_kill (pthread_t threadid, int signo); +libc_hidden_proto (__pthread_kill) extern void __pthread_exit (void *value) __attribute__ ((__noreturn__)); libc_hidden_proto (__pthread_exit) extern int __pthread_join (pthread_t threadid, void **thread_return); diff --git a/nptl/pthread_kill.c b/nptl/pthread_kill.c index 71c362adce..d79531c10c 100644 --- a/nptl/pthread_kill.c +++ b/nptl/pthread_kill.c @@ -31,32 +31,40 @@ __pthread_kill (pthread_t threadid, int signo) sigset_t set; __libc_signal_block_all (&set); - int val; - - /* Force load of pd->tid into local variable or register. Otherwise - if a thread exits between ESRCH test and tgkill, we might return - EINVAL, because pd->tid would be cleared by the kernel. */ + pid_t tid; struct pthread *pd = (struct pthread *) threadid; - pid_t tid = atomic_forced_read (pd->tid); - if (__glibc_unlikely (tid <= 0)) - /* Not a valid thread handle. */ - val = ESRCH; + + if (pd == THREAD_SELF) + tid = INLINE_SYSCALL_CALL (gettid); else - { - /* We have a special syscall to do the work. */ - pid_t pid = __getpid (); + /* Force load of pd->tid into local variable or register. Otherwise + if a thread exits between ESRCH test and tgkill, we might return + EINVAL, because pd->tid would be cleared by the kernel. */ + tid = atomic_forced_read (pd->tid); + + int val; + if (__glibc_likely (tid > 0)) + { + pid_t pid = __getpid (); - val = INTERNAL_SYSCALL_CALL (tgkill, pid, tid, signo); - val = (INTERNAL_SYSCALL_ERROR_P (val) - ? INTERNAL_SYSCALL_ERRNO (val) : 0); - } + val = INTERNAL_SYSCALL_CALL (tgkill, pid, tid, signo); + val = (INTERNAL_SYSCALL_ERROR_P (val) + ? INTERNAL_SYSCALL_ERRNO (val) : 0); + } + else + val = ESRCH; __libc_signal_restore_set (&set); return val; } +/* 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) +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) +# if OTHER_SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_34) compat_symbol (libc, __pthread_kill, pthread_kill, GLIBC_2_0); +# endif #endif diff --git a/nptl/pthread_self.c b/nptl/pthread_self.c index f877a2e6bd..196d93fb8e 100644 --- a/nptl/pthread_self.c +++ b/nptl/pthread_self.c @@ -20,7 +20,9 @@ #include pthread_t -pthread_self (void) +__pthread_self (void) { return (pthread_t) THREAD_SELF; } +libc_hidden_def (__pthread_self) +weak_alias (__pthread_self, pthread_self) diff --git a/sysdeps/htl/pthreadP.h b/sysdeps/htl/pthreadP.h index 8e2cf2ce65..3b357b7bdc 100644 --- a/sysdeps/htl/pthreadP.h +++ b/sysdeps/htl/pthreadP.h @@ -31,8 +31,6 @@ extern void __pthread_init_static_tls (struct link_map *) attribute_hidden; /* These represent the interface used by glibc itself. */ -extern pthread_t __pthread_self (void); -extern int __pthread_kill (pthread_t threadid, int signo); extern struct __pthread **__pthread_threads; extern int __pthread_mutex_init (pthread_mutex_t *__mutex, const pthread_mutexattr_t *__attr); diff --git a/sysdeps/posix/raise.c b/sysdeps/posix/raise.c index 9fdb4d538b..4806c0cc63 100644 --- a/sysdeps/posix/raise.c +++ b/sysdeps/posix/raise.c @@ -16,13 +16,20 @@ . */ #include -#include +#include +#include /* Raise the signal SIG. */ int raise (int sig) { - return __kill (__getpid (), sig); + int ret = __pthread_kill (__pthread_self (), sig); + if (ret != 0) + { + __set_errno (ret); + ret = -1; + } + return ret; } libc_hidden_def (raise) weak_alias (raise, gsignal) diff --git a/sysdeps/unix/sysv/linux/raise.c b/sysdeps/unix/sysv/linux/raise.c deleted file mode 100644 index 9be3b37f53..0000000000 --- a/sysdeps/unix/sysv/linux/raise.c +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright (C) 2002-2021 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2002. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include -#include -#include -#include -#include -#include - -int -raise (int sig) -{ - /* rt_sigprocmask may fail if: - - 1. sigsetsize != sizeof (sigset_t) (EINVAL) - 2. a failure in copy from/to user space (EFAULT) - 3. an invalid 'how' operation (EINVAL) - - The first case is already handle in glibc syscall call by using the arch - defined _NSIG. Second case is handled by using a stack allocated mask. - The last one should be handled by the block/unblock functions. */ - - sigset_t set; - __libc_signal_block_app (&set); - - pid_t pid = INTERNAL_SYSCALL_CALL (getpid); - pid_t tid = INTERNAL_SYSCALL_CALL (gettid); - - int ret = INLINE_SYSCALL_CALL (tgkill, pid, tid, sig); - - __libc_signal_restore_set (&set); - - return ret; -} -libc_hidden_def (raise) -weak_alias (raise, gsignal)