From owner-freebsd-threads@FreeBSD.ORG Sat Feb 19 18:10:13 2011 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 21E021065673 for ; Sat, 19 Feb 2011 18:10:13 +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 D7F088FC1C for ; Sat, 19 Feb 2011 18:10:12 +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 p1JIACSE075491 for ; Sat, 19 Feb 2011 18:10:12 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.4/8.14.4/Submit) id p1JIACTi075490; Sat, 19 Feb 2011 18:10:12 GMT (envelope-from gnats) Resent-Date: Sat, 19 Feb 2011 18:10:12 GMT Resent-Message-Id: <201102191810.p1JIACTi075490@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, KOSAKI Motohiro Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 195E3106566C for ; Sat, 19 Feb 2011 18:09:54 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from red.freebsd.org (red.freebsd.org [IPv6:2001:4f8:fff6::22]) by mx1.freebsd.org (Postfix) with ESMTP id 07E2D8FC12 for ; Sat, 19 Feb 2011 18:09:54 +0000 (UTC) Received: from red.freebsd.org (localhost [127.0.0.1]) by red.freebsd.org (8.14.4/8.14.4) with ESMTP id p1JI9rDc063562 for ; Sat, 19 Feb 2011 18:09:53 GMT (envelope-from nobody@red.freebsd.org) Received: (from nobody@localhost) by red.freebsd.org (8.14.4/8.14.4/Submit) id p1JI9rZi063561; Sat, 19 Feb 2011 18:09:53 GMT (envelope-from nobody) Message-Id: <201102191809.p1JI9rZi063561@red.freebsd.org> Date: Sat, 19 Feb 2011 18:09:53 GMT From: KOSAKI Motohiro To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Cc: Subject: threads/154893: pthread_sigmask don't work if mask and oldmask are passed the same pointer X-BeenThere: freebsd-threads@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Threading on FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 19 Feb 2011 18:10:13 -0000 >Number: 154893 >Category: threads >Synopsis: pthread_sigmask don't work if mask and oldmask are passed the same pointer >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-threads >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Sat Feb 19 18:10:12 UTC 2011 >Closed-Date: >Last-Modified: >Originator: KOSAKI Motohiro >Release: 8.1 >Organization: >Environment: FreeBSD FreeBSD8 8.1-RELEASE FreeBSD 8.1-RELEASE #0: Mon Jul 19 02:36:49 UTC 2010 root@mason.cse.buffalo.edu:/\ usr/obj/usr/src/sys/GENERIC amd64 >Description: Programmers expect pthread_sigmask(SIG_SETMASK, &msk, &msk) mean 1) rewritten signal mask by msk. 2) and, return old signal mask to msk. But, FreeBSD doesn't. Its pthread_sigmask behave the same as pthread_sigmask(SIG_SETMASK, NULL, &msk). It is very strange to me. Sidenote: man sigprocmask says its type is below. int sigprocmask(int how, const sigset_t * restrict set, sigset_t * restrict oset); It is not POSIX compliant nor user friendly. But the man page clealy describe set==oset is invalid. At least, pthread_sigmask's man page shold be fixed if uthread maintainers woun't fix this issue. Sidenote2: This is a source of signal breakage of ruby trunk. http://redmine.ruby-lang.org/issues/show/4173 >How-To-Repeat: run following program ------------------------------------------------------ #include #include #include void* func(void* arg) { sigset_t old; sigset_t add; int i; sigemptyset(&old); pthread_sigmask(SIG_BLOCK, NULL, &old); printf("before: "); for (i=0; i<4; i++) printf(" %08x", old.__bits[i]); printf("\n"); sigemptyset(&add); sigaddset(&add, SIGUSR1); pthread_sigmask(SIG_BLOCK, &add, NULL); pthread_sigmask(SIG_BLOCK, NULL, &old); printf("after: "); for (i=0; i<4; i++) printf(" %08x", old.__bits[i]); printf("\n"); return 0; } void* func2(void* arg) { sigset_t old; sigset_t add; int i; sigemptyset(&old); pthread_sigmask(SIG_BLOCK, NULL, &old); printf("before: "); for (i=0; i<4; i++) printf(" %08x", old.__bits[i]); printf("\n"); sigemptyset(&add); sigaddset(&add, SIGUSR1); pthread_sigmask(SIG_BLOCK, &add, &old); printf("after: "); for (i=0; i<4; i++) printf(" %08x", old.__bits[i]); printf("\n"); return 0; } int main(void) { pthread_t thr; void* ret; printf("correct case: \n"); pthread_create(&thr, NULL, func, NULL); pthread_join(thr, &ret); printf("incorrect case: \n"); pthread_create(&thr, NULL, func2, NULL); pthread_join(thr, &ret); return 0; } >Fix: /usr/src/lib/libc_r/uthread/uthread_sigmask.c has following code. ----------------------------------------------------------------- int _pthread_sigmask(int how, const sigset_t *set, sigset_t *oset) { struct pthread *curthread = _get_curthread(); sigset_t sigset; int ret = 0; /* Check if the existing signal process mask is to be returned: */ if (oset != NULL) { /* Return the current mask: */ *oset = curthread->sigmask; // (1) } /* Check if a new signal set was provided by the caller: */ if (set != NULL) { (snip) } ---------------------------------------------------- Then, if set == oset, set argument was override before use it at (1). To introduce temporary variable fix this issue easily. >Release-Note: >Audit-Trail: >Unformatted: