Bug 25110

Summary: pthread signal handler fails after forking
Product: Base System Reporter: jagarl <jagarl>
Component: binAssignee: Daniel Eischen <deischen>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 4.2-RELEASE   
Hardware: Any   
OS: Any   

Description jagarl 2001-02-15 11:10:01 UTC
The signal handler in libc_r (thread_sig_handler) requires alternative
stack frame because thread_sigframe_add() changes the original stack.
If signal stack is disabled and thread_sig_handler() is called with
the original stack, thread_sigframe_add() destroys his own stack.

Thread_init() calls sigaltstack() and sets the alternative signal stack.
But alternative stack is disabled by the process forking. Then the signal
handler fails and the process only receives SIGKILL and SIGSTOP signals.

Fix: 

After forking, define the alternative stack manually and the problem solves.

If the invalidation of the signal stack at forking is correct,
sigaltstack() must be called somewhere in lib/libc_r/uthread/uthread_fork.c.
If the signal stack should be copied to the new process, P_ALTSTACK flag in
the process's p_flag must be copied somewhere in sys/kern/kern_fork.c.
How-To-Repeat: Running this program. The parent process stops at waitpid() call.
The child process can only be stopped by 'kill -KILL pid' command.

(It must be compiled with pthread. For example, cc -pthread sample.c)

#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>

static void handler(int signo) {
        fprintf(stderr,"handler called!\n");
        _exit(0);
}

int main(void) {
        int i;
        pid_t pid, pid2; int status;

        pid = fork();
        if (pid == -1) return 0;
        if (pid == 0) {
                /* child process */
                signal(SIGTERM,handler);
                while(1) ;
                _exit(0);
        }
        /* parent process */
        sleep(1);
        kill(pid, SIGTERM);
        fprintf(stderr, "waitpid start\n");
        waitpid(pid, &status, 0);
        fprintf(stderr, "waitpid end\n");

        return 0;
}
Comment 1 Akinori MUSHA freebsd_committer freebsd_triage 2001-04-17 23:32:22 UTC
Responsible Changed
From-To: freebsd-bugs->deischen

He maintains libc_r and has a fix.
Comment 2 Daniel Eischen freebsd_committer freebsd_triage 2001-04-18 13:42:21 UTC
State Changed
From-To: open->closed

Fix applied to -current.  Will apply to -stable in a few 
days or when the code freeze is over (whichever comes 
last).