From owner-freebsd-bugs@FreeBSD.ORG Fri Aug 6 14:50:03 2010 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 5371D1065678 for ; Fri, 6 Aug 2010 14:50:03 +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 15B728FC16 for ; Fri, 6 Aug 2010 14:50:03 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.4/8.14.4) with ESMTP id o76Eo2u0015364 for ; Fri, 6 Aug 2010 14:50:02 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.4/8.14.4/Submit) id o76Eo2tQ015363; Fri, 6 Aug 2010 14:50:02 GMT (envelope-from gnats) Resent-Date: Fri, 6 Aug 2010 14:50:02 GMT Resent-Message-Id: <201008061450.o76Eo2tQ015363@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Fernando Lemos Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 2176A106567A for ; Fri, 6 Aug 2010 14:40:50 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21]) by mx1.freebsd.org (Postfix) with ESMTP id 045C48FC1D for ; Fri, 6 Aug 2010 14:40:50 +0000 (UTC) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.14.3/8.14.3) with ESMTP id o76EeneW012896 for ; Fri, 6 Aug 2010 14:40:49 GMT (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.14.3/8.14.3/Submit) id o76Een1G012895; Fri, 6 Aug 2010 14:40:49 GMT (envelope-from nobody) Message-Id: <201008061440.o76Een1G012895@www.freebsd.org> Date: Fri, 6 Aug 2010 14:40:49 GMT From: Fernando Lemos To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Cc: Subject: misc/149366: pthread_cleanup_pop never runs the configured routine X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 06 Aug 2010 14:50:03 -0000 >Number: 149366 >Category: misc >Synopsis: pthread_cleanup_pop never runs the configured routine >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Fri Aug 06 14:50:02 UTC 2010 >Closed-Date: >Last-Modified: >Originator: Fernando Lemos >Release: 7.2-p8 >Organization: NetFilter >Environment: FreeBSD iron.netfilter.com.br 7.2-RELEASE-p8 FreeBSD 7.2-RELEASE-p8 #0: Wed May 26 03:08:50 UTC 2010 root@i386-builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC i386 >Description: The pthread_cleanup_pop docs say: "The pthread_cleanup_pop() function shall remove the routine at the top of the calling thread's cancellation cleanup stack and optionally invoke it (if execute is non-zero)." However, in the attached sample, we invoke pthread_cleanup_pop with execute non-zero and still the routine isn't called. I got to reproduce it consistently in FreeBSD 7.2 and also in one FreeBSD 7.0-PRERELEASE box, so I think it might even affect newer versions (I don't have access to a box running 7.3 or 8.x). If pthread_cleanup_pop doesn't work properly, all sorts of deadlocks and races are possible, not to mention resource leaks, so this is kind of important (although I don't think pthread_cleanup_pop is widely used). TIA, >How-To-Repeat: The attached sample C file can be used. To compile it, run "gcc -O0 -ggdb -o test main.c", for example. Run it with "gdb test". Break on release_update_lock. You'll see that it never gets called. Compare the outputs, first a Linux machine: Init Res: 0 Locking read Res: 0 Unlocking Res: 0 Locking write Res: 0 Unlocking Res: 0 Locking read Res: 0 Unlocking with cleanup pop release_update_rwlock: 0 Locking write Res: 0 Unlocking Res: 0 Now a FreeBSD 7.2-p8 machine: Init Res: 0 Locking read Res: 0 Unlocking Res: 0 Locking write Res: 0 Unlocking Res: 0 Locking read Res: 0 Unlocking with cleanup pop Locking write Res: 0 Unlocking Res: 0 Note how release_update_rwlock is never called (and gdb confirms it). >Fix: Patch attached with submission follows: #include #include static pthread_rwlock_t trava; static void release_update_rwlock(void *dummy) { int res = pthread_rwlock_unlock(&trava); printf("release_update_rwlock: %d\n", res); } int main(int argc, char **argv) { printf("Init\n"); int res = pthread_rwlock_init(&trava, NULL); printf("Res: %d\n", res); printf("Locking read\n"); res = pthread_rwlock_rdlock(&trava); printf("Res: %d\n", res); printf("Unlocking\n"); res = pthread_rwlock_unlock(&trava); printf("Res: %d\n", res); printf("Locking write\n"); res = pthread_rwlock_wrlock(&trava); printf("Res: %d\n", res); printf("Unlocking\n"); res = pthread_rwlock_unlock(&trava); printf("Res: %d\n", res); printf("Locking read\n"); res = pthread_rwlock_rdlock(&trava); printf("Res: %d\n", res); printf("Unlocking with cleanup pop\n"); pthread_cleanup_push(&release_update_rwlock, NULL); pthread_cleanup_pop(1); printf("Locking write\n"); res = pthread_rwlock_wrlock(&trava); printf("Res: %d\n", res); printf("Unlocking\n"); res = pthread_rwlock_unlock(&trava); printf("Res: %d\n", res); return 0; } >Release-Note: >Audit-Trail: >Unformatted: