From patchwork Tue May 12 15:02:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 38974 X-Patchwork-Delegate: carlos@redhat.com 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 81F183938C36; Tue, 12 May 2020 15:02:46 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 81F183938C36 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1589295766; bh=/yPDkGqRNewduRjSYTklZ+xHI9i/SyeS+6xqjz9yr8o=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=yP5zD+PGN3MDgprHGGBLArXtZSx17xW+YEe9xmWkwHFchMYFmj1zlY4k4ex6IUzKJ aE8E0HqeNwR8/lghiPxelPvWLvDXibSf+BPKuwHgGx0WYu4bKZhDIJpZ+cQt2gVty3 bK8s/NpYqy4T7XYmxSFZDi3U4x5D14hnzNjmGuq4= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from us-smtp-delivery-1.mimecast.com (us-smtp-1.mimecast.com [207.211.31.81]) by sourceware.org (Postfix) with ESMTP id 24B89383F844 for ; Tue, 12 May 2020 15:02:44 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 24B89383F844 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-379-Kgxr6ZLmN5qxSKc87lhDDQ-1; Tue, 12 May 2020 11:02:42 -0400 X-MC-Unique: Kgxr6ZLmN5qxSKc87lhDDQ-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 00D86461; Tue, 12 May 2020 15:02:41 +0000 (UTC) Received: from oldenburg2.str.redhat.com (ovpn-114-41.ams2.redhat.com [10.36.114.41]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 258D36CA57; Tue, 12 May 2020 15:02:35 +0000 (UTC) To: libc-alpha@sourceware.org Subject: [PATCH] nptl: Provide a way to block all signals for the timer helper thread Date: Tue, 12 May 2020 17:02:34 +0200 Message-ID: <87a72d5h85.fsf@oldenburg2.str.redhat.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.3 (gnu/linux) MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-14.2 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_PASS, TXREP 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: Florian Weimer via Libc-alpha From: Florian Weimer Reply-To: Florian Weimer Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" timer_create needs to create threads with all signals blocked, including SIGTIMER (which happens to equal SIGCANCEL). Add a new internal interface which provides an explicit way to achieve that. Fixes commit b3cae39dcbfa2432b3f3aa28854d8ac57f0de1b8 ("nptl: Start new threads with all signals blocked [BZ #25098]"). Tested on x86_64-linux-gnu. ----- nptl/Versions | 1 + nptl/pthreadP.h | 10 +++++++++ nptl/pthread_create.c | 36 +++++++++++++++++++++++--------- sysdeps/unix/sysv/linux/timer_routines.c | 16 ++++++-------- 4 files changed, 43 insertions(+), 20 deletions(-) Reviewed-by: Adhemerval Zanella Tested-by: Carlos O'Donell diff --git a/nptl/Versions b/nptl/Versions index f7140277f5..17a711dfb1 100644 --- a/nptl/Versions +++ b/nptl/Versions @@ -285,5 +285,6 @@ libpthread { __pthread_barrier_init; __pthread_barrier_wait; __shm_directory; __libpthread_freeres; + __pthread_create_internal; } } diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h index c4e72f57a9..4e065ace58 100644 --- a/nptl/pthreadP.h +++ b/nptl/pthreadP.h @@ -339,6 +339,16 @@ extern void __pthread_cleanup_upto (__jmp_buf target, char *targetframe); hidden_proto (__pthread_cleanup_upto) #endif +/* Exactly like pthread_create if NEW_SIGMASK == NULL. Otherwise, do + not use the current signal mask for the new thread, but set it to + *NEW_SIGMASK instead (without unblocking internal signals). */ +extern int __pthread_create_internal (pthread_t *newthread, + const pthread_attr_t *attr, + void *(*start_routine) (void *), + void *arg, const sigset_t *new_sigmask); +#if IS_IN (libpthread) +hidden_proto (__pthread_create_internal) +#endif /* Functions with versioned interfaces. */ extern int __pthread_create_2_1 (pthread_t *newthread, diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c index afd379e89a..2430d65723 100644 --- a/nptl/pthread_create.c +++ b/nptl/pthread_create.c @@ -603,10 +603,10 @@ report_thread_creation (struct pthread *pd) return false; } - int -__pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr, - void *(*start_routine) (void *), void *arg) +__pthread_create_internal (pthread_t *newthread, const pthread_attr_t *attr, + void *(*start_routine) (void *), void *arg, + const sigset_t *new_sigmask) { STACK_VARIABLES; @@ -762,14 +762,21 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr, sigset_t original_sigmask; __libc_signal_block_all (&original_sigmask); - /* Conceptually, the new thread needs to inherit the signal mask of - this thread. Therefore, it needs to restore the saved signal - mask of this thread, so save it in the startup information. */ - pd->sigmask = original_sigmask; + if (new_sigmask != NULL) + /* The caller supplied the signal mask for the new thread. */ + pd->sigmask = *new_sigmask; + else + { + /* Conceptually, the new thread needs to inherit the signal mask + of this thread. Therefore, it needs to restore the saved + signal mask of this thread, so save it in the startup + information. */ + pd->sigmask = original_sigmask; - /* Reset the cancellation signal mask in case this thread is running - cancellation. */ - __sigdelset (&pd->sigmask, SIGCANCEL); + /* Reset the cancellation signal mask in case this thread is + running cancellation. */ + __sigdelset (&pd->sigmask, SIGCANCEL); + } /* Start the thread. */ if (__glibc_unlikely (report_thread_creation (pd))) @@ -873,6 +880,15 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr, return retval; } +hidden_def (__pthread_create_internal) + +int +__pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr, + void *(*start_routine) (void *), void *arg) +{ + return __pthread_create_internal (newthread, attr, start_routine, arg, + false); +} versioned_symbol (libpthread, __pthread_create_2_1, pthread_create, GLIBC_2_1); diff --git a/sysdeps/unix/sysv/linux/timer_routines.c b/sysdeps/unix/sysv/linux/timer_routines.c index 63083f6f91..7a5fa3dbb2 100644 --- a/sysdeps/unix/sysv/linux/timer_routines.c +++ b/sysdeps/unix/sysv/linux/timer_routines.c @@ -136,23 +136,19 @@ __start_helper_thread (void) (void) pthread_attr_init (&attr); (void) pthread_attr_setstacksize (&attr, __pthread_get_minstack (&attr)); - /* Block all signals in the helper thread but SIGSETXID. To do this - thoroughly we temporarily have to block all signals here. The - helper can lose wakeups if SIGTIMER is not blocked throughout. */ - sigset_t ss; - __libc_signal_block_app (&ss); - __libc_signal_block_sigtimer (NULL); + /* Block all signals in the helper thread but SIGSETXID. */ + sigset_t new_sigmask; + __sigfillset (&new_sigmask); + __sigdelset (&new_sigmask, SIGSETXID); /* Create the helper thread for this timer. */ pthread_t th; - int res = pthread_create (&th, &attr, timer_helper_thread, NULL); + int res = __pthread_create_internal (&th, &attr, timer_helper_thread, NULL, + &new_sigmask); if (res == 0) /* We managed to start the helper thread. */ __helper_tid = ((struct pthread *) th)->tid; - /* Restore the signal mask. */ - __libc_signal_restore_set (&ss); - /* No need for the attribute anymore. */ (void) pthread_attr_destroy (&attr);