Bug#551470: Processes hang after signal handler return
Package: libc0.3
Version: 2.9-27
When using a sigaltstack, under some circumstances returning from a signal handler causes the process to block on a spinlock indefinitely. This problem is specific to Hurd. I've attached a small demonstration program. This is either a kernel or libc bug.
The expected output is:
terpstra@orange:~$ ./sigbug
Starting with stack bfd789c0
Alarm in 5 seconds
Waiting for signal.
Got sigint with stack b7dead24
On hurd we now enter an indefinite spin_lock (hang)
Clean exit
On hurd the output is:
terpstra@strauss:~$ ./sigbug
Starting with stack 1024ddc
Alarm in 5 seconds
Waiting for signal.
Got sigint with stack 1411efc
On hurd we now enter an indefinite spin_lock (hang)
... then it hangs consuming CPU resources:
terpstra@strauss:~$ ps -xM
PID STAT TIME COMMAND
24645 R 0:02.62 ./sigbug
terpstra@strauss:~$ ps -xM
PID STAT TIME COMMAND
24645 R 0:03.12 ./sigbug
A stack trace of the program:
(gdb) bt
#0 0x0105690c in swtch_pri ()
at /build/buildd/eglibc-2.9/build-tree/hurd-i386-libc/mach/swtch_pri.S:2
#1 0x01058204 in __spin_lock_solid (lock=0x120880c) at spin-solid.c:27
#2 0x010961b8 in __spin_lock (how=2, set=0x1411edc, oset=0x0)
at ../mach/lock-intern.h:55
#3 __sigprocmask (how=2, set=0x1411edc, oset=0x0)
at ../sysdeps/mach/hurd/sigprocmask.c:43
#4 0x01099eae in abort () at abort.c:65
#5 0x0109795b in __sigreturn (scp=0x1411f20)
at ../sysdeps/mach/hurd/i386/sigreturn.c:74
#6 0x01071cf6 in trampoline () from /lib/libc.so.0.3
#7 0x01411f20 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
Compile the test program as:
terpstra@strauss:~$ gcc -Wall -O0 -g sigbug.c -o sigbug
Here is the test program:
terpstra@strauss:~$ cat sigbug.c
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
void f(int s) {
int x;
printf("Got sigint with stack %lx\n", (long)&x);
printf("On hurd we now enter an indefinite spin_lock (hang)\n");
}
int main() {
struct sigaction sa;
stack_t altstack;
sigset_t mask;
printf("Starting with stack %lx\n", (long)&sa);
memset(&altstack, 0, sizeof(altstack));
altstack.ss_size = 1024*1024;
altstack.ss_sp = malloc(2*altstack.ss_size);
altstack.ss_sp += altstack.ss_size;
sigaltstack(&altstack, 0);
memset(&sa, 0, sizeof(sa));
sigfillset(&sa.sa_mask);
sa.sa_handler = f;
sa.sa_flags = SA_ONSTACK;
sigaction(SIGALRM, &sa, 0);
printf("Alarm in 5 seconds\n");
alarm(5);
printf("Waiting for signal.\n");
sigemptyset(&mask);
sigsuspend(&mask);
printf("Clean exit\n");
return 0;
}
Reply to: