[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: