From owner-freebsd-bugs Thu Jan 25 9:50:21 2001 Delivered-To: freebsd-bugs@hub.freebsd.org Received: from freefall.freebsd.org (freefall.FreeBSD.org [216.136.204.21]) by hub.freebsd.org (Postfix) with ESMTP id BA90E37B6A2 for ; Thu, 25 Jan 2001 09:50:00 -0800 (PST) Received: (from gnats@localhost) by freefall.freebsd.org (8.11.1/8.11.1) id f0PHo0r52221; Thu, 25 Jan 2001 09:50:00 -0800 (PST) (envelope-from gnats) Received: from freefall.freebsd.org (freefall.FreeBSD.org [216.136.204.21]) by hub.freebsd.org (Postfix) with ESMTP id 78ECA37B69F for ; Thu, 25 Jan 2001 09:48:08 -0800 (PST) Received: (from nobody@localhost) by freefall.freebsd.org (8.11.1/8.11.1) id f0PHm8B52012; Thu, 25 Jan 2001 09:48:08 -0800 (PST) (envelope-from nobody) Message-Id: <200101251748.f0PHm8B52012@freefall.freebsd.org> Date: Thu, 25 Jan 2001 09:48:08 -0800 (PST) From: earl_chew@agilent.com To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-1.0 Subject: misc/24641: pthread_rwlock_rdlock can deadlock Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org >Number: 24641 >Category: misc >Synopsis: pthread_rwlock_rdlock can deadlock >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Thu Jan 25 09:50:00 PST 2001 >Closed-Date: >Last-Modified: >Originator: Earl Chew >Release: 3.3-RELEASE >Organization: Agilent Technologies >Environment: FreeBSD qar1 3.3-RELEASE FreeBSD 3.3-RELEASE #0: Tue Oct 17 16:21:01 EDT 2000 >Description: The man page for pthread_rwlock_rdlock() says: A thread may hold multiple concurrent read locks. If so, pthread_rwlock_unlock() must be called once for each lock obtained. I tried this out after reading Bill Lewis' article on Usenet: http://x64.deja.com/[ST_rn=ps]/getdoc.xp?AN=573590892&search=thread&CONTEXT=980444523.1181483044&HIT_CONTEXT=980444500.1181483040&HIT_NUM=11&hitnum=3 Bill wrote: Consider: T1 gets a read lock. T2 wants a write lock & blocks, waiting for T1. Now T1 wants a read lock again. Because writers have priority, T1 will now block, waiting for T2. My test program prints the following, then gets stuck: > ./a.out Attempt to acquire read lock first Acquired read lock first Attempt to acquire write lock Attempt to acquire read lock second Examining the source code (uthread_rwlock.c,v 1.5) it is pretty clear why this deadlock occurs (as Bill Lewis predicts). >How-To-Repeat: #include #include #include #include static pthread_rwlock_t rwlock1 = PTHREAD_RWLOCK_INITIALIZER; static volatile int wrStarted; void * wrfunc(void *) { 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 *) { 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, char**) { pthread_t wrt; pthread_t rdt; pthread_attr_t a; 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); assert(pthread_detach(wrt) == 0); assert(pthread_detach(rdt) == 0); return 0; } >Fix: >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message