[hurd,commited] htl: Fix race between timedrd/wrlock and unlock

Samuel Thibault <[email protected]>
Newsgroups gmane.os.hurd.cvs,gmane.comp.lib.glibc.alpha
Message-ID <[email protected]>
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 <[email protected]> '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
-- 
2.51.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.