| Summary: | siglongjmp does not properly restore the signal stack | ||
|---|---|---|---|
| Product: | Base System | Reporter: | Bram <Bram> |
| Component: | bin | Assignee: | Marcel Moolenaar <marcel> |
| Status: | Closed FIXED | ||
| Severity: | Affects Only Me | ||
| Priority: | Normal | ||
| Version: | Unspecified | ||
| Hardware: | Any | ||
| OS: | Any | ||
Responsible Changed From-To: freebsd-bugs->marcel Marcel said he would take a look at it and get it to the right person if he can't fix it. State Changed From-To: open->closed This has been fixed more than 9 months ago. The PR stayed open while I was focusing on other things. Ah well... :-) |
When using siglongjmp() to jump from a signal handler back to the main code, while the signal function uses the signal stack (defined with sigaltstack()), this works only once. The next time the signal handler is called the program crashes, apparently because the signal stack is not operating. Setting the signal stack again (with sigaltstack()) works around the problem. The same code works fine on other systems that have sigaltstack(). Fix: No known solution How-To-Repeat: Compile and run the program below. Result: In while Signal recieved! In while Illegal instruction(core dumped) Now define "WORKAROUND" and do it again. Result: In while Signal recieved! In while Signal recieved! In while Signal recieved! etc. #include <signal.h> #include <stdio.h> #include <setjmp.h> #include <stdlib.h> #include <string.h> /* #define WORKAROUND */ sigjmp_buf env; stack_t ss; struct sigaction sa; void foo(void) { int a[32768]; foo(); /* recursively call ourselves until out of stack space */ } void sighandler(int sig) { siglongjmp(env, 100); } main() { if ((ss.ss_sp = malloc(SIGSTKSZ)) == NULL) exit(1); ss.ss_size = SIGSTKSZ; ss.ss_flags = 0; if (sigaltstack(&ss,(stack_t *)0) < 0) { perror("sigaltstack"); exit(1); } sa.sa_handler = sighandler; sa.sa_flags = SA_ONSTACK; if (sigaction(SIGSEGV, &sa, 0) < 0) { perror("sigaction"); exit(1); } while (1) { puts("In while"); if (!sigsetjmp(env, 1)) foo(); else { puts("Signal recieved!"); #ifdef WORKAROUND if (sigaltstack(&ss, (stack_t *)0) < 0) { perror("sigaltstack"); exit(1); } #endif } } }