I just spent the last two days tracking down a bug that turned out to be in
PTH's rwlock implementation. The problem has to do with an incorrect
assumption about readers.

        pth_rwlock_acquire contains the following code:

        rwlock->rw_readers++;
        if (rwlock->rw_readers == 1) {
            if (!pth_mutex_acquire(&(rwlock->rw_mutex_rw), tryonly,
ev_extra))
            {
                rwlock->rw_readers--;
                errno_shield { pth_mutex_release(&(rwlock->rw_mutex_rd)); }
                return FALSE;
            }

        Basically, what this says is that the first thread to acquire a read lock
locks the rw_mutex_rw lock, which ensures that no writers manage to get the
lock while anyone is reading. The code to unlock this looks like this:

        rwlock->rw_readers--;
        if (rwlock->rw_readers == 0) {
            if (!pth_mutex_release(&(rwlock->rw_mutex_rw))) {
                rwlock->rw_readers++;
                errno_shield { pth_mutex_release(&(rwlock->rw_mutex_rd)); }
                return FALSE;
            }
        }

        This says that the last reader to release the lock releases the rw_mutex_rw
lock, allowing a writer to get the lock now that there are no readers.
However, pth_mutex_release looks like this:

    if (mutex == NULL)
        return_errno(FALSE, EINVAL);
    if (!(mutex->mx_state & PTH_MUTEX_INITIALIZED))
        return_errno(FALSE, EDEADLK);
    if (!(mutex->mx_state & PTH_MUTEX_LOCKED))
        return_errno(FALSE, EDEADLK);
    if (mutex->mx_owner != pth_current)
        return_errno(FALSE, EACCES);

        Note the last two lines, which say that a mutex can only be unlocked by the
thread that locked it. However, there is no reason to expect the thread that
got the first read lock to be the same as the thread that releases the last
read lock -- the locks can be released by various threads in any order.

        This causes the attempt to release the last read lock to fail (with
EACCESS).

        I have not had a chance to check later releases, but since 1.3.7 is the
latest release version, a bugfix release seems to be warranted even if the
bug is fixed in the latest release.

        As a quick fix, have the rwlock_release code release the mutex itself,
avoiding the check that the releasing thread is the same as the thread that
holds the mutex.

        David Schwartz

______________________________________________________________________
GNU Portable Threads (Pth)            http://www.gnu.org/software/pth/
User Support Mailing List                            [EMAIL PROTECTED]
Automated List Manager (Majordomo)           [EMAIL PROTECTED]

Reply via email to