From patchwork Wed Mar 4 01:25: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: 131044 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 3F51C4BA2E12 for ; Wed, 4 Mar 2026 01:26:23 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 3F51C4BA2E12 X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from sonata.ens-lyon.org (sonata.ens-lyon.org [140.77.166.138]) by sourceware.org (Postfix) with ESMTPS id C704D4BA2E1B for ; Wed, 4 Mar 2026 01:25:51 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C704D4BA2E1B 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 C704D4BA2E1B 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=1772587551; cv=none; b=xwjz5cJydbGvfjfP79HcD4oA5dPGbREGTY3xbUbGqPIuzEEETlCme+a9ZIAmVWdwT8LGRXMN7HD3exFyzpRLMBvmcBucGot+iH50R2jHeWI/pnqXRZV+tJZ1eeHU5uLzrH4UuZQdPuapNNQjTjcAsGjCpFTdYS05VlzDxbFAmwc= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1772587551; c=relaxed/simple; bh=gg7gacqJ2R19CZ1hx/qe9ZzA5iICrpG5KYagTPYUMSA=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=LepBnBZVFnMxkidtqkIRqL69q37eslH3BjC8Ith49xzjSQLthGtTASZOBq25bcWBTaIAaxEOQvWOuyU6Lo7mPWptw9Wmsg80Ah4DeHnqpFYz7Y5l/1570OnEObLvGsW/V1funFr4ugC7Ad1QF98R0b9V+Q1vlhcJynrdkJJGavY= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org C704D4BA2E1B Received: from localhost (localhost [127.0.0.1]) by sonata.ens-lyon.org (Postfix) with ESMTP id B9A2CA0261; Wed, 4 Mar 2026 02:25: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 FERJiEW58PEs; Wed, 4 Mar 2026 02:25: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 95448A022D; Wed, 4 Mar 2026 02:25:50 +0100 (CET) Received: from samy by end with local (Exim 4.99.1) (envelope-from ) id 1vxazm-00000005fhG-0Syg; Wed, 04 Mar 2026 02:25:50 +0100 From: Samuel Thibault To: libc-alpha@sourceware.org Cc: Samuel Thibault , commit-hurd@gnu.org, Brent Baccala Subject: [hurd,commited] htl: Fix race between timedrd/wrlock and unlock Date: Wed, 4 Mar 2026 02:25:49 +0100 Message-ID: <20260304012549.1351915-1-samuel.thibault@ens-lyon.org> X-Mailer: git-send-email 2.51.0 MIME-Version: 1.0 X-Spam-Status: No, score=-12.2 required=5.0 tests=BAYES_00, GIT_PATCH_0, JMQ_SPF_NEUTRAL, KAM_DMARC_STATUS, RCVD_IN_DNSWL_BLOCKED, RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED, SPF_HELO_PASS, SPF_PASS, TXREP 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 In case the rwlock is unlocked right before we time out, we will have been given ownership, so we shouldn't time out. Reported-by: Brent Baccala 's Claude assistant --- sysdeps/htl/pt-rwlock-timedrdlock.c | 41 +++++++++++++---------------- sysdeps/htl/pt-rwlock-timedwrlock.c | 35 +++++++++++------------- 2 files changed, 35 insertions(+), 41 deletions(-) diff --git a/sysdeps/htl/pt-rwlock-timedrdlock.c b/sysdeps/htl/pt-rwlock-timedrdlock.c index 41671e40f9..25b761433a 100644 --- a/sysdeps/htl/pt-rwlock-timedrdlock.c +++ b/sysdeps/htl/pt-rwlock-timedrdlock.c @@ -31,7 +31,6 @@ __pthread_rwlock_timedrdlock_internal (struct __pthread_rwlock *rwlock, const struct timespec *abstime) { error_t err; - int drain; struct __pthread *self; __pthread_spin_wait (&rwlock->__lock); @@ -85,35 +84,33 @@ __pthread_rwlock_timedrdlock_internal (struct __pthread_rwlock *rwlock, __pthread_spin_wait (&rwlock->__lock); if (self->prevp == NULL) - /* Another thread removed us from the queue, which means a wakeup message - has been sent. It was either consumed while we were blocking, or - queued after we timed out and before we acquired the rwlock lock, in - which case the message queue must be drained. */ - drain = err ? 1 : 0; + { + /* Another thread removed us from the queue, which means it gave us + ownership and a wakeup message has been sent. It was either consumed + while we were blocking, or queued after we timed out and before we + acquired the rwlock lock, in which case the message queue must be + drained. */ + __pthread_spin_unlock (&rwlock->__lock); + if (err) + /* We have not consumed the message, do it now. */ + __pthread_block (self); + + /* The reader count has already been increment by whoever woke us + up. */ + + assert (rwlock->__readers > 0); + + return 0; + } else { /* We're still in the queue. No one attempted to wake us up, i.e. we timed out. */ __pthread_dequeue (self); - drain = 0; - } - __pthread_spin_unlock (&rwlock->__lock); - - if (drain) - __pthread_block (self); - - if (err) - { + __pthread_spin_unlock (&rwlock->__lock); assert (err == ETIMEDOUT); return err; } - - /* The reader count has already been increment by whoever woke us - up. */ - - assert (rwlock->__readers > 0); - - return 0; } int diff --git a/sysdeps/htl/pt-rwlock-timedwrlock.c b/sysdeps/htl/pt-rwlock-timedwrlock.c index 6b202a25dd..841d1f9101 100644 --- a/sysdeps/htl/pt-rwlock-timedwrlock.c +++ b/sysdeps/htl/pt-rwlock-timedwrlock.c @@ -31,7 +31,6 @@ __pthread_rwlock_timedwrlock_internal (struct __pthread_rwlock *rwlock, const struct timespec *abstime) { error_t err; - int drain; struct __pthread *self; __pthread_spin_wait (&rwlock->__lock); @@ -71,32 +70,30 @@ __pthread_rwlock_timedwrlock_internal (struct __pthread_rwlock *rwlock, __pthread_spin_wait (&rwlock->__lock); if (self->prevp == NULL) - /* Another thread removed us from the queue, which means a wakeup message - has been sent. It was either consumed while we were blocking, or - queued after we timed out and before we acquired the rwlock lock, in - which case the message queue must be drained. */ - drain = err ? 1 : 0; + { + /* Another thread removed us from the queue, which means it gave us + ownership and a wakeup message has been sent. It was either consumed + while we were blocking, or queued after we timed out and before we + acquired the rwlock lock, in which case the message queue must be + drained. */ + __pthread_spin_unlock (&rwlock->__lock); + if (err) + /* We have not consumed the message, do it now. */ + __pthread_block (self); + + assert (rwlock->__readers == 0); + + return 0; + } else { /* We're still in the queue. No one attempted to wake us up, i.e. we timed out. */ __pthread_dequeue (self); - drain = 0; - } - __pthread_spin_unlock (&rwlock->__lock); - - if (drain) - __pthread_block (self); - - if (err) - { + __pthread_spin_unlock (&rwlock->__lock); assert (err == ETIMEDOUT); return err; } - - assert (rwlock->__readers == 0); - - return 0; } int