public inbox for glibc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug libc/28957] New: pthread rwlocks Do Not Prevent Race Condition
@ 2022-03-10 22:45 gavin.d.howard at gmail dot com
  2022-03-15 19:02 ` [Bug libc/28957] " gavin.d.howard at gmail dot com
  2022-03-15 21:21 ` gavin.d.howard at gmail dot com
  0 siblings, 2 replies; 3+ messages in thread
From: gavin.d.howard at gmail dot com @ 2022-03-10 22:45 UTC (permalink / raw)
  To: glibc-bugs

https://sourceware.org/bugzilla/show_bug.cgi?id=28957

            Bug ID: 28957
           Summary: pthread rwlocks Do Not Prevent Race Condition
           Product: glibc
           Version: 2.33
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: libc
          Assignee: unassigned at sourceware dot org
          Reporter: gavin.d.howard at gmail dot com
                CC: drepper.fsp at gmail dot com
  Target Milestone: ---
            Target: Linux 5.15.26-gentoo-x86_64

Hello,

The write lock of the pthread_rwlock_t type in glibc appears to sometimes allow
multiple threads to have write access at the same time.

Background: I am building a build system that uses multiple threads.

When the build system is about to run a command, it takes a read lock, and then
it consults a map of command names to paths. For example, if the command was
`gcc -c -o test.o test.c`, then it would look up "gcc" in the map.

If an entry exists, the value is the full path to the executable, and that is
what is used for the argv[0], so if the value is found, it is copied, the read
lock is released, and all is good.

If no entry exists, then the read lock is released, and there is a lookup of
the executable in PATH. Once it is found and the entry is ready to be inserted
into the map, a write lock is taken. Then it checks again to see if an entry
exists. If not it inserts the new entry.

At that point, the write lock is released, and it goes back to the beginning,
takes the read lock, gets the entry, releases the read lock, and then continues
on its merry way.

While I can't provide the actual code because of licensing issues, I can give
some pseudo-code:

```
do
{
  cont = false;

  r = pthread_rwlock_rdlock(&lock);
  <check r>

  if (map_exists(map, cmd))
  {
    path = map_at(map, cmd);

    r = pthread_rwlock_unlock(&lock);
    <check r>
  }
  else
  {
    r = pthread_rwlock_unlock(&lock);
    <check r>

    <Search PATH and prepare entry>

    r = pthread_rwlock_wrlock(&lock);
    <check r>

    if (!map_exists(&map, cmd))
    {
      err = map_insert(&map, cmd, entry);
      if (err == ELEM_EXISTS) abort();
    }

    r = pthread_rwlock_unlock(&lock);
    <check r>

    cont = true;
  }
}
while (cont);
```

With that code, I can get my build system to `abort()` within 10 minutes,
consistently, by running it over and over again bootstrapping itself.

If I change the `pthread_rwlock_rdlock()` to a `pthread_rwlock_wrlock()`, the
`abort()` can still be triggered within 10 minutes, so it appears that it is
not an issue of using a read lock in the wrong place.

In addition, if I change `lock` to be a mutex and update all of the locking and
unlocking appropriately, I cannot trigger the abort() even with 12+ hours of
trying. I think that this means that I am not using the rwlocks wrong, but that
there is some bug in the write lock of the rwlock.

I'm attempting to create a small reproducer that I can publish, but so far, no
luck.

Any help would be greatly appreciated.

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

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2022-03-15 21:21 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-10 22:45 [Bug libc/28957] New: pthread rwlocks Do Not Prevent Race Condition gavin.d.howard at gmail dot com
2022-03-15 19:02 ` [Bug libc/28957] " gavin.d.howard at gmail dot com
2022-03-15 21:21 ` gavin.d.howard at gmail dot com

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).