Skip site navigation (1)Skip section navigation (2)
Date:      Sun,  5 Jul 2009 15:40:16 +0200 (CEST)
From:      Rink Springer <rink@FreeBSD.org>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   threads/136345: Recursive read rwlocks in thread A cause deadlock with write lock in thread B
Message-ID:  <20090705134016.CB1286D41E@mx1.rink.nu>
Resent-Message-ID: <200907051400.n65E0Ae5074934@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>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@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:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20090705134016.CB1286D41E>