threads/136345: Recursive read rwlocks in thread A cause deadlock
with write lock in thread B
Rink Springer
rink at FreeBSD.org
Sun Jul 5 14:00:11 UTC 2009
>Number: 136345
>Category: threads
>Synopsis: Recursive read rwlocks in thread A cause deadlock with write lock in thread B
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: freebsd-threads
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Sun Jul 05 14:00:10 UTC 2009
>Closed-Date:
>Last-Modified:
>Originator: Rink Springer
>Release: FreeBSD 7.2-PRERELEASE amd64
>Organization:
>Environment:
System: FreeBSD gloom.rink.nu 7.2-PRERELEASE FreeBSD 7.2-PRERELEASE #1 r191417: Thu Apr 23 13:53:08 CEST 2009 rink at gloom.rink.nu:/usr/obj/extra0/sources/releng7/sys/GENERIC amd64
The problem is also present in HEAD as of today.
>Description:
The following program deadlocks on FreeBSD in the 'urdlck' state:
---
#include <pthread.h>
#include <stdio.h>
pthread_rwlock_t rwl_lock;
void*
thread1(void* x)
{
while(1) {
pthread_rwlock_rdlock(&rwl_lock);
printf("read1\n");
pthread_rwlock_rdlock(&rwl_lock);
printf("read2\n");
pthread_rwlock_unlock(&rwl_lock);
pthread_rwlock_unlock(&rwl_lock);
}
return NULL;
}
void*
thread2(void* x)
{
while(1) {
pthread_rwlock_wrlock(&rwl_lock);
printf("write\n");
pthread_rwlock_unlock(&rwl_lock);
}
return NULL;
}
int
main()
{
pthread_t thr_1, thr_2;
pthread_rwlock_init(&rwl_lock, NULL);
pthread_create(&thr_1, NULL, thread1, NULL);
pthread_create(&thr_1, NULL, thread2, NULL);
pthread_join(thr_1, NULL);
return 0;
}
---
The problem is that it acquires a read rwlock multiple times in one thread, and tries to acquire a write rwlock in another thread.
>How-To-Repeat:
$ gcc -o locktest locktest.c -pthread
$ ./locktest
... output ...
load: 0.00 cmd: locktest 72866 [urdlck] 1.38r 0.01u 0.00s 0% 1360k
and it's deadlocked. Note that POSIX states that 'A thread may hold multiple concurrent read locks on rwlock (that is, successfully call the pthread_rwlock_rdlock() function n times). If so, the application shall ensure that the thread performs matching unlocks (that is, it calls the pthread_rwlock_unlock() function n times).', which seems to imply that the program above shouldn't deadlock.
The program above works fine on Linux, yet it also seems to deadlock on Solaris 8. I have yet to check more recent versions of Solaris.
>Fix:
Don't Do That[tm]; it seems the only fix is to restructure the application to avoid this scenario, even though POSIX seems to allow it.
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-threads
mailing list