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>