Subject: lib/24899: pthread_sigmask can loop to death
To: None <gnats-bugs@gnats.NetBSD.org>
From: None <lha@netbsd.org>
List: netbsd-bugs
Date: 03/24/2004 14:36:45
>Number:         24899
>Category:       lib
>Synopsis:       pthread_sigmask can loop to death
>Confidential:   no
>Severity:       critical
>Priority:       medium
>Responsible:    lib-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Mar 24 13:37:00 UTC 2004
>Closed-Date:
>Last-Modified:
>Originator:     Love
>Release:        NetBSD 1.6ZK
>Organization:
	
>Environment:
	
	
System: NetBSD nutcracker.stacken.kth.se 1.6ZK NetBSD 1.6ZK (NUTCRACKER) #50: Tue Mar 23 23:43:50 CET 2004 lha@nutcracker.stacken.kth.se:/sources/netbsd/current/src/sys/arch/i386/compile/NUTCRACKER i386
Architecture: i386
Machine: i386
>Description:
	compile openafs current, start fileserver, see it hang in 


This GDB was configured as "i386--netbsdelf"...
(gdb) r -d 100
Starting program: /sources/afs/openafs-current/o/src/tviced/fileserver -d 100
^C
Program received signal SIGINT, Interrupt.
0x48128a36 in __sigismember14 () from /usr/lib/libc.so.12
(gdb) bt
#0  0x48128a36 in __sigismember14 () from /usr/lib/libc.so.12
#1  0x480e4088 in pthread_sigmask (how=3, set=0x4abfff98, oset=0x0)
    at /sources/netbsd/current/src/lib/libpthread/pthread_sig.c:601
#2  0x0806b60d in softsig_thread (arg=0x0) at ../../../src/util/softsig.c:54
#3  0x480eaad0 in pthread__create_tramp (start=0x806b5cc <softsig_thread>, 
    arg=0x0) at /sources/netbsd/current/src/lib/libpthread/pthread.c:413
(gdb) up
#1  0x480e4088 in pthread_sigmask (how=3, set=0x4abfff98, oset=0x0)
    at /sources/netbsd/current/src/lib/libpthread/pthread_sig.c:601
601                     if (!__sigismember14(&self->pt_sigmask, i)) {
(gdb) p set
$1 = (const sigset_t *) 0x4abfff98
(gdb) p *set
$2 = {__bits = {4294965575, 4294967295, 4294967295, 4294967295}}
(gdb) n
Single stepping until exit from function __sigismember14, 
which has no line number information.
pthread_sigmask (how=3, set=0x4abfff98, oset=0x0)
    at /sources/netbsd/current/src/lib/libpthread/pthread_sig.c:600
600             while ((i = firstsig(&self->pt_siglist)) != 0) {
(gdb) 
601                     if (!__sigismember14(&self->pt_sigmask, i)) {
(gdb) p i
$3 = 30
(gdb) n
0x480e0208 in _init () from /usr/lib/libpthread.so.0
(gdb) n
Single stepping until exit from function _init, 
which has no line number information.
pthread_sigmask (how=3, set=0x4abfff98, oset=0x0)
    at /sources/netbsd/current/src/lib/libpthread/pthread_sig.c:600
600             while ((i = firstsig(&self->pt_siglist)) != 0) {
(gdb) n
601                     if (!__sigismember14(&self->pt_sigmask, i)) {
(gdb) n
0x480e0208 in _init () from /usr/lib/libpthread.so.0
(gdb) n
Single stepping until exit from function _init, 
which has no line number information.
pthread_sigmask (how=3, set=0x4abfff98, oset=0x0)
    at /sources/netbsd/current/src/lib/libpthread/pthread_sig.c:600
600             while ((i = firstsig(&self->pt_siglist)) != 0) {
(gdb) n
601                     if (!__sigismember14(&self->pt_sigmask, i)) {
(gdb) p i
$4 = 30
(gdb) p self->pt_siglist
$5 = {__bits = {536870912, 0, 0, 0}}
(gdb) p/x self->pt_siglist
$6 = {__bits = {0x20000000, 0x0, 0x0, 0x0}}
(gdb) list
596             }
597
598             /* See if there are any signals to take */
599             __sigemptyset14(&takelist);
600             while ((i = firstsig(&self->pt_siglist)) != 0) {
601                     if (!__sigismember14(&self->pt_sigmask, i)) {
602                             __sigaddset14(&takelist, i);
603                             __sigdelset14(&self->pt_siglist, i);
604                     }
605             }

See how the code above is a infinite loop in case of signal is present
in self->pt_siglist but not in self->pt_sigmask, since the signal
isn't removed from self->pt_siglist.



>How-To-Repeat:
	see above
>Fix:

Index: pthread_sig.c
===================================================================
RCS file: /sources/netbsd/NetBSD-cvs/src/lib/libpthread/pthread_sig.c,v
retrieving revision 1.33
diff -u -u -w -r1.33 pthread_sig.c
--- src/lib/libpthread/pthread_sig.c	2 Jan 2004 19:24:44 -0000	1.33
+++ src/lib/libpthread/pthread_sig.c	24 Mar 2004 13:30:38 -0000
@@ -597,11 +597,13 @@
 
 	/* See if there are any signals to take */
 	__sigemptyset14(&takelist);
-	while ((i = firstsig(&self->pt_siglist)) != 0) {
+	tmp = self->pt_siglist;
+	while ((i = firstsig(&tmp)) != 0) {
 		if (!__sigismember14(&self->pt_sigmask, i)) {
 			__sigaddset14(&takelist, i);
 			__sigdelset14(&self->pt_siglist, i);
 		}
+		__sigdelset14(&tmp, i);
 	}
 	pthread_spinlock(self, &pt_process_siglock);
 	while ((i = firstsig(&pt_process_siglist)) != 0) {

>Release-Note:
>Audit-Trail:
>Unformatted: