From owner-freebsd-threads@FreeBSD.ORG Sun Jul 5 14:00:11 2009 Return-Path: Delivered-To: freebsd-threads@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id E21241065673 for ; Sun, 5 Jul 2009 14:00:10 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id AE7188FC15 for ; Sun, 5 Jul 2009 14:00:10 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.14.3/8.14.3) with ESMTP id n65E0A3e074935 for ; Sun, 5 Jul 2009 14:00:10 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.3/8.14.3/Submit) id n65E0Ae5074934; Sun, 5 Jul 2009 14:00:10 GMT (envelope-from gnats) Resent-Date: Sun, 5 Jul 2009 14:00:10 GMT Resent-Message-Id: <200907051400.n65E0Ae5074934@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-threads@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Rink Springer Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 260DA1065670 for ; Sun, 5 Jul 2009 13:54:58 +0000 (UTC) (envelope-from rink@rink.nu) Received: from mx1.rink.nu (gloom.rink.nu [213.34.49.2]) by mx1.freebsd.org (Postfix) with ESMTP id DE0048FC12 for ; Sun, 5 Jul 2009 13:54:57 +0000 (UTC) (envelope-from rink@rink.nu) Received: from localhost (localhost [127.0.0.1]) by mx1.rink.nu (Postfix) with ESMTP id 72FD96D423 for ; Sun, 5 Jul 2009 15:40:18 +0200 (CEST) Received: from mx1.rink.nu ([213.34.49.2]) by localhost (gloom.rink.nu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id DpV7L8z4iRSO for ; Sun, 5 Jul 2009 15:40:16 +0200 (CEST) Received: by mx1.rink.nu (Postfix, from userid 1000) id CB1286D41E; Sun, 5 Jul 2009 15:40:16 +0200 (CEST) Message-Id: <20090705134016.CB1286D41E@mx1.rink.nu> Date: Sun, 5 Jul 2009 15:40:16 +0200 (CEST) From: Rink Springer To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Cc: Subject: threads/136345: Recursive read rwlocks in thread A cause deadlock with write lock in thread B X-BeenThere: freebsd-threads@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: Rink Springer List-Id: Threading on FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 05 Jul 2009 14:00:11 -0000 >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 #include 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: