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: