[Bug nptl/23861] New: rdlock stalls indefinitely on an unlocked pthread rwlock

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

[Bug nptl/23861] New: rdlock stalls indefinitely on an unlocked pthread rwlock

albert.aribaud at 3adev dot fr
https://sourceware.org/bugzilla/show_bug.cgi?id=23861

            Bug ID: 23861
           Summary: rdlock stalls indefinitely on an unlocked pthread
                    rwlock
           Product: glibc
           Version: 2.28
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: nptl
          Assignee: unassigned at sourceware dot org
          Reporter: prohaska7 at gmail dot com
                CC: drepper.fsp at gmail dot com
  Target Milestone: ---

Created attachment 11382
  --> https://sourceware.org/bugzilla/attachment.cgi?id=11382&action=edit
test program that exposes rdlock stall

Sometimes a thread can be stalled indefinitely inside rdlock even when the
rwlock is not locked with either a reader or a writer.  This bug is specific to
the PREFER_WRITER_NONRECURSIVE kind of pthread rwlock.  

Problem occurs on Ubuntu 18.10 using glibc 2.28.  It probably occurs on
previous versions of glibc as well.

The problem can be reproduced with the attached test program:

for ((x=1;x<100;x++)) ; do echo $x;date;./wrloop
--prefer-writer-nonrecursive;done

The stall inside rdlock occurs because the expected value for the futex wait
does not have the RWAITING bit set.  This causes rdlock to immediately return
EAGAIN, so essentially rdlock just spins.  Sometimes, the futex wait stalls
forever because the expected value matches the value of __readers due to a race
and then the futex __readers is never waked again because RWAITING is turned
off.

This patch fixes the problem:

diff --git a/nptl/pthread_rwlock_common.c b/nptl/pthread_rwlock_common.c
index a290d08332..81b162bbee 100644
--- a/nptl/pthread_rwlock_common.c
+++ b/nptl/pthread_rwlock_common.c
@@ -310,6 +310,7 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
          if (atomic_compare_exchange_weak_relaxed
              (&rwlock->__data.__readers, &r, r | PTHREAD_RWLOCK_RWAITING))
            {
+              r |= PTHREAD_RWLOCK_RWAITING;
              /* Wait for as long as the flag is set.  An ABA situation is
                 harmless because the flag is just about the state of
                 __readers, and all threads set the flag under the same

--
You are receiving this mail because:
You are on the CC list for the bug.
Reply | Threaded
Open this post in threaded view
|

[Bug nptl/23861] rdlock stalls indefinitely on an unlocked pthread rwlock

albert.aribaud at 3adev dot fr
https://sourceware.org/bugzilla/show_bug.cgi?id=23861

--- Comment #1 from Andreas Schwab <[hidden email]> ---
I think the inner loop should update r with the current value of __readers.

--
You are receiving this mail because:
You are on the CC list for the bug.
Reply | Threaded
Open this post in threaded view
|

[Bug nptl/23861] rdlock stalls indefinitely on an unlocked pthread rwlock

albert.aribaud at 3adev dot fr
In reply to this post by albert.aribaud at 3adev dot fr
https://sourceware.org/bugzilla/show_bug.cgi?id=23861

--- Comment #2 from richard prohaska <prohaska7 at gmail dot com> ---
This patch sets r = __readers in the inner loop as suggested and runs the test
program successfully.

diff --git a/nptl/pthread_rwlock_common.c b/nptl/pthread_rwlock_common.c
index a290d08332..8c970d19c3 100644
--- a/nptl/pthread_rwlock_common.c
+++ b/nptl/pthread_rwlock_common.c
@@ -314,7 +314,7 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
                 harmless because the flag is just about the state of
                 __readers, and all threads set the flag under the same
                 conditions.  */
-             while ((atomic_load_relaxed (&rwlock->__data.__readers)
+                while (((r = atomic_load_relaxed (&rwlock->__data.__readers))
                  & PTHREAD_RWLOCK_RWAITING) != 0)
                {
                  int private = __pthread_rwlock_get_private (rwlock);

--
You are receiving this mail because:
You are on the CC list for the bug.