kern/24641: pthread_rwlock_rdlock can deadlock
Craig Rodrigues
rodrigc at FreeBSD.org
Sun Jun 4 17:30:48 PDT 2006
Synopsis: pthread_rwlock_rdlock can deadlock
State-Changed-From-To: open->closed
State-Changed-By: rodrigc
State-Changed-When: Mon Jun 5 00:28:27 UTC 2006
State-Changed-Why:
Problem does not occur in libpthread in FreeBSD 6.x.
Your testcase needs to be modified slightly.
If you call pthread_join(),
then if you call pthread_detach() later on, pthread_detach
may return EINVAL, because the thread may already be
terminated and detached, so you can't detach it.
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
static pthread_rwlock_t rwlock1 = PTHREAD_RWLOCK_INITIALIZER;
static volatile int wrStarted;
void * wrfunc(void *unused)
{
wrStarted = 1;
printf("Attempt to acquire write lock\n");
assert(pthread_rwlock_wrlock(&rwlock1) == 0);
printf("Acquired write lock\n");
assert(pthread_rwlock_unlock(&rwlock1) == 0);
return 0;
}
static volatile int rdStarted;
void * rdfunc(void *unused)
{
printf("Attempt to acquire read lock first\n");
assert(pthread_rwlock_rdlock(&rwlock1) == 0);
printf("Acquired read lock first\n");
rdStarted = 1;
while (wrStarted == 0)
sleep(1);
printf("Attempt to acquire read lock second\n");
assert(pthread_rwlock_rdlock(&rwlock1) == 0);
printf("Acquired read lock second\n");
assert(pthread_rwlock_unlock(&rwlock1) == 0);
assert(pthread_rwlock_unlock(&rwlock1) == 0);
return 0;
}
int
main(int argc, char **argv)
{
pthread_t wrt;
pthread_t rdt;
pthread_attr_t a;
int ret;
assert(pthread_rwlock_init(&rwlock1, 0) == 0);
assert(pthread_attr_init(&a) == 0);
assert(pthread_create(&rdt, &a, rdfunc, NULL) == 0);
while (rdStarted == 0)
sleep(1);
assert(pthread_create(&wrt, &a, wrfunc, NULL) == 0);
assert(pthread_join(wrt, 0) == 0);
assert(pthread_join(rdt, 0) == 0);
assert(pthread_rwlock_destroy(&rwlock1) == 0);
if ((ret = pthread_detach(wrt)) != 0) {
if (ret == EINVAL) {
printf("wrt already detached\n");
}
}
if ((ret = pthread_detach(rdt)) != 0) {
if (errno == EINVAL) {
printf("rdt already detached\n");
}
}
return 0;
}
http://www.freebsd.org/cgi/query-pr.cgi?pr=24641
More information about the freebsd-threads
mailing list