From patchwork Wed Feb 4 23:12:49 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Samuel Thibault X-Patchwork-Id: 129590 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [127.0.0.1]) by sourceware.org (Postfix) with ESMTP id 830B64BA2E0E for ; Wed, 4 Feb 2026 23:13:22 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 830B64BA2E0E X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from sonata.ens-lyon.org (domu-toccata.ens-lyon.fr [140.77.166.138]) by sourceware.org (Postfix) with ESMTPS id A9DAC4BA2E10 for ; Wed, 4 Feb 2026 23:12:51 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org A9DAC4BA2E10 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=ens-lyon.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=bounce.ens-lyon.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org A9DAC4BA2E10 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=140.77.166.138 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1770246771; cv=none; b=FSiYrSKbyWP5VtHRM8DS01DQyYAswTlfH+YToUrvCzW0f3anNF24ewNjjPp/86V7mJ7cx4fz9wHdq8SwTd+wh/ydFC8JgLoMD67rRhTggDoOCdhMNhaMuhinkfxuDVwPalPNq4PV1YEbAhbu+49I46u+VjoWTaO7vYM/i54A62Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1770246771; c=relaxed/simple; bh=V+lEd7DgT85IvytnGa2GMGs+tILTWt9FDQaGMeUK34U=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=PCj8ocAyrZB7Hrd4EEJX866GW6TlE3MQNDnUhxWJ8eZpcrj4wJ+oH3xVv0jH/0Aublmv2Xj5w9B0SJi2/iUF8WJT/lDWGL+YFVDJKrUImQY1lS15k0Nf+43UU6lfDpBi/RceOkcNagE2t6FniVzjlk2QmLjgLxUE2cSu6qWBDgY= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A9DAC4BA2E10 Received: from localhost (localhost [127.0.0.1]) by sonata.ens-lyon.org (Postfix) with ESMTP id 89393A20EC; Thu, 5 Feb 2026 00:12:50 +0100 (CET) Received: from sonata.ens-lyon.org ([127.0.0.1]) by localhost (sonata.ens-lyon.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id uLWUtr5ABDHW; Thu, 5 Feb 2026 00:12:50 +0100 (CET) Received: from end (aamiens-653-1-40-48.w83-192.abo.wanadoo.fr [83.192.199.48]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by sonata.ens-lyon.org (Postfix) with ESMTPSA id 5A0FEA1CAD; Thu, 5 Feb 2026 00:12:50 +0100 (CET) Received: from samy by end with local (Exim 4.99.1) (envelope-from ) id 1vnm3F-00000005avT-3kYf; Thu, 05 Feb 2026 00:12:49 +0100 From: Samuel Thibault To: libc-alpha@sourceware.org Cc: Samuel Thibault , commit-hurd@gnu.org, Michael Banck Subject: [hurd,commited] hurd: Take cancel_lock in critical section Date: Thu, 5 Feb 2026 00:12:49 +0100 Message-ID: <20260204231249.1333576-1-samuel.thibault@ens-lyon.org> X-Mailer: git-send-email 2.51.0 MIME-Version: 1.0 X-Spam-Status: No, score=-13.0 required=5.0 tests=BAYES_00, GIT_PATCH_0, JMQ_SPF_NEUTRAL, KAM_DMARC_STATUS, KAM_SHORT, RCVD_IN_DNSWL_BLOCKED, RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED, SPF_HELO_PASS, SPF_PASS, TXREP, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces~patchwork=sourceware.org@sourceware.org read/write etc. shall be signal-safe, and take cancel_lock, so we have to defer signal delivery while holding cancel_lock. Reported-by: Michael Banck --- htl/cancellation.c | 5 +++++ htl/pt-cancel.c | 14 +++++++++++++- htl/pt-internal.h | 2 +- htl/pt-setcancelstate.c | 3 +++ htl/pt-setcanceltype.c | 3 +++ htl/pt-testcancel.c | 3 +++ sysdeps/htl/pt-cond-timedwait.c | 4 ++++ sysdeps/mach/hurd/htl/pt-docancel.c | 5 ++++- 8 files changed, 36 insertions(+), 3 deletions(-) diff --git a/htl/cancellation.c b/htl/cancellation.c index ba3b82bbb7..272c4a70b6 100644 --- a/htl/cancellation.c +++ b/htl/cancellation.c @@ -16,6 +16,7 @@ License along with the GNU C Library; if not, see . */ +#include #include #include #include @@ -25,10 +26,12 @@ int __pthread_enable_asynccancel (void) struct __pthread *p = _pthread_self (); int oldtype; + HURD_CRITICAL_BEGIN; __pthread_mutex_lock (&p->cancel_lock); oldtype = p->cancel_type; p->cancel_type = PTHREAD_CANCEL_ASYNCHRONOUS; __pthread_mutex_unlock (&p->cancel_lock); + HURD_CRITICAL_END; __pthread_testcancel (); @@ -39,7 +42,9 @@ void __pthread_disable_asynccancel (int oldtype) { struct __pthread *p = _pthread_self (); + HURD_CRITICAL_BEGIN; __pthread_mutex_lock (&p->cancel_lock); p->cancel_type = oldtype; __pthread_mutex_unlock (&p->cancel_lock); + HURD_CRITICAL_END; } diff --git a/htl/pt-cancel.c b/htl/pt-cancel.c index b376575742..b80c6018be 100644 --- a/htl/pt-cancel.c +++ b/htl/pt-cancel.c @@ -16,6 +16,7 @@ License along with the GNU C Library; if not, see . */ +#include #include #include @@ -27,15 +28,22 @@ __pthread_cancel (pthread_t t) { int err = 0; struct __pthread *p; + struct __pthread *self = _pthread_self (); + void *hurd_critical = NULL; p = __pthread_getid (t); if (p == NULL) return ESRCH; + if (p == self) + hurd_critical = _hurd_critical_section_lock (); + __pthread_mutex_lock (&p->cancel_lock); if (p->cancel_pending) { __pthread_mutex_unlock (&p->cancel_lock); + if (p == self) + _hurd_critical_section_unlock (hurd_critical); return 0; } @@ -44,12 +52,14 @@ __pthread_cancel (pthread_t t) if (p->cancel_state != PTHREAD_CANCEL_ENABLE) { __pthread_mutex_unlock (&p->cancel_lock); + if (p == self) + _hurd_critical_section_unlock (hurd_critical); return 0; } if (p->cancel_type == PTHREAD_CANCEL_ASYNCHRONOUS) /* CANCEL_LOCK is unlocked by this call. */ - err = __pthread_do_cancel (p); + err = __pthread_do_cancel (p, hurd_critical); else { if (p->cancel_hook != NULL) @@ -59,6 +69,8 @@ __pthread_cancel (pthread_t t) __pthread_mutex_unlock (&p->cancel_lock); } + if (p == self) + _hurd_critical_section_unlock (hurd_critical); return err; } diff --git a/htl/pt-internal.h b/htl/pt-internal.h index e23e7bccc3..5a3104830c 100644 --- a/htl/pt-internal.h +++ b/htl/pt-internal.h @@ -292,7 +292,7 @@ libc_hidden_proto (__pthread_wakeup) /* Perform a cancelation. The CANCEL_LOCK member of the given thread must be locked before calling this function, which must unlock it. */ -extern int __pthread_do_cancel (struct __pthread *thread); +extern int __pthread_do_cancel (struct __pthread *thread, void *hurd_critical); /* Initialize the thread specific data structures. THREAD must be the diff --git a/htl/pt-setcancelstate.c b/htl/pt-setcancelstate.c index 6e42c35741..69a4cc825c 100644 --- a/htl/pt-setcancelstate.c +++ b/htl/pt-setcancelstate.c @@ -16,6 +16,7 @@ License along with the GNU C Library; if not, see . */ +#include #include #include #include @@ -35,6 +36,7 @@ __pthread_setcancelstate (int state, int *oldstate) break; } + HURD_CRITICAL_BEGIN; __pthread_mutex_lock (&p->cancel_lock); if (oldstate != NULL) *oldstate = p->cancel_state; @@ -44,6 +46,7 @@ __pthread_setcancelstate (int state, int *oldstate) /* Do not achieve cancel when called again, notably from __pthread_exit itself. */ p->cancel_pending = 2; __pthread_mutex_unlock (&p->cancel_lock); + HURD_CRITICAL_END; if (cancelled) __pthread_exit (PTHREAD_CANCELED); diff --git a/htl/pt-setcanceltype.c b/htl/pt-setcanceltype.c index e71f2fc2fd..dd02aea75c 100644 --- a/htl/pt-setcanceltype.c +++ b/htl/pt-setcanceltype.c @@ -16,6 +16,7 @@ License along with the GNU C Library; if not, see . */ +#include #include #include #include @@ -35,12 +36,14 @@ __pthread_setcanceltype (int type, int *oldtype) break; } + HURD_CRITICAL_BEGIN; __pthread_mutex_lock (&p->cancel_lock); if (oldtype != NULL) *oldtype = p->cancel_type; p->cancel_type = type; cancelled = (p->cancel_state == PTHREAD_CANCEL_ENABLE) && p->cancel_pending && (p->cancel_type == PTHREAD_CANCEL_ASYNCHRONOUS); __pthread_mutex_unlock (&p->cancel_lock); + HURD_CRITICAL_END; if (cancelled) __pthread_exit (PTHREAD_CANCELED); diff --git a/htl/pt-testcancel.c b/htl/pt-testcancel.c index 6fb27f91ca..a8c17ef479 100644 --- a/htl/pt-testcancel.c +++ b/htl/pt-testcancel.c @@ -16,6 +16,7 @@ License along with the GNU C Library; if not, see . */ +#include #include #include @@ -28,9 +29,11 @@ __pthread_testcancel (void) struct __pthread *p = _pthread_self (); int cancelled; + HURD_CRITICAL_BEGIN; __pthread_mutex_lock (&p->cancel_lock); cancelled = (p->cancel_state == PTHREAD_CANCEL_ENABLE) && p->cancel_pending; __pthread_mutex_unlock (&p->cancel_lock); + HURD_CRITICAL_END; if (cancelled) __pthread_exit (PTHREAD_CANCELED); diff --git a/sysdeps/htl/pt-cond-timedwait.c b/sysdeps/htl/pt-cond-timedwait.c index 3920af3b8b..d350868c2b 100644 --- a/sysdeps/htl/pt-cond-timedwait.c +++ b/sysdeps/htl/pt-cond-timedwait.c @@ -16,6 +16,7 @@ License along with the GNU C Library; if not, see . */ +#include #include #include #include @@ -117,6 +118,7 @@ __pthread_cond_timedwait_internal (pthread_cond_t *cond, This function contains inline implementations of pthread_testcancel and pthread_setcanceltype to reduce locking overhead. */ + HURD_CRITICAL_BEGIN; __pthread_mutex_lock (&self->cancel_lock); cancelled = (self->cancel_state == PTHREAD_CANCEL_ENABLE) && self->cancel_pending; @@ -124,6 +126,7 @@ __pthread_cond_timedwait_internal (pthread_cond_t *cond, if (cancelled) { __pthread_mutex_unlock (&self->cancel_lock); + HURD_CRITICAL_UNLOCK; __pthread_exit (PTHREAD_CANCELED); } @@ -145,6 +148,7 @@ __pthread_cond_timedwait_internal (pthread_cond_t *cond, __pthread_spin_unlock (&cond->__lock); __pthread_mutex_unlock (&self->cancel_lock); + HURD_CRITICAL_END; /* Increase the waiter reference count. Relaxed MO is sufficient because we only need to synchronize when decrementing the reference count. diff --git a/sysdeps/mach/hurd/htl/pt-docancel.c b/sysdeps/mach/hurd/htl/pt-docancel.c index a4167708c3..709f2507bd 100644 --- a/sysdeps/mach/hurd/htl/pt-docancel.c +++ b/sysdeps/mach/hurd/htl/pt-docancel.c @@ -29,8 +29,9 @@ call_exit (void) } int -__pthread_do_cancel (struct __pthread *p) +__pthread_do_cancel (struct __pthread *p, void *hurd_critical) { + struct __pthread *self = _pthread_self (); mach_port_t ktid; int me; @@ -38,6 +39,8 @@ __pthread_do_cancel (struct __pthread *p) assert (p->cancel_state == PTHREAD_CANCEL_ENABLE); __pthread_mutex_unlock (&p->cancel_lock); + if (p == self) + _hurd_critical_section_unlock (hurd_critical); ktid = __mach_thread_self (); me = p->kernel_thread == ktid;