The sigaction(2) manpage states that the signal stack is inherited by the child after fork(2), but the signal stack is not inherited in fact. The attached test program checks if the sigaltstack(2) setting is inherited by the child or not. The result of the program is: original: sp=0x0 size=0 flags=4 changed: sp=0x8049a20 size=1048576 flags=0 child: sp=0x8049a20 size=1048576 flags=4 <- flags: 4 parent: sp=0x8049a20 size=1048576 flags=0 but it should be: original: sp=0x0 size=0 flags=4 changed: sp=0x8049a20 size=1048576 flags=0 child: sp=0x8049a20 size=1048576 flags=0 <- flags: 0 parent: sp=0x8049a20 size=1048576 flags=0 The parent had cleared the SS_DISABLE flag of ss_flags (in struct sigaltstack) and forked the child, but SS_DISABLE is set on the child. The following patch against sys/kern/kern_fork.c fixes this problem: Index: sys/kern/kern_fork.c =================================================================== RCS file: /usr/local/share/cvsup/cvsroot/src/sys/kern/kern_fork.c,v retrieving revision 1.103 diff -u -r1.103 kern_fork.c --- sys/kern/kern_fork.c 2001/02/28 02:53:43 1.103 +++ sys/kern/kern_fork.c 2001/03/02 12:45:40 @@ -461,7 +461,7 @@ * Preserve some more flags in subprocess. P_PROFIL has already * been preserved. */ - p2->p_flag |= p1->p_flag & P_SUGID; + p2->p_flag |= p1->p_flag & (P_SUGID | P_ALTSTACK); if (p1->p_session->s_ttyvp != NULL && p1->p_flag & P_CONTROLT) p2->p_flag |= P_CONTROLT; if (flags & RFPPWAIT)
#include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #include <signal.h> #include <stdio.h> #include <assert.h> #define ALTSTACKSIZE (1024 * 1024) static u_int64_t altstack[ALTSTACKSIZE / sizeof(u_int64_t)]; static void print_sigstack(char *info) { struct sigaltstack ss; int ret; ret = sigaltstack(NULL, &ss); if (ret < 0) { perror("sigaltstack"); exit(1); } printf("%10s: sp=%p size=%d flags=%x\n", info, ss.ss_sp, ss.ss_size, ss.ss_flags); fflush(stdout); } int main(int argc, char *argv[]) { struct sigaltstack ss; pid_t pid; int ret; print_sigstack("original"); ss.ss_sp = (char *)altstack; ss.ss_size = sizeof(altstack); ss.ss_flags = 0; ret = sigaltstack(&ss, NULL); if (ret < 0) { perror("sigaltstack"); exit(1); } print_sigstack("changed"); pid = fork(); if (pid < 0) { perror("fork"); exit(1); } if (pid == 0) { print_sigstack("child"); exit(0); } wait(NULL); print_sigstack("parent"); return 0; }