Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 15 Feb 2001 03:04:19 -0800 (PST)
From:      jagarl@creator.club.ne.jp
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   bin/25110: pthread signal handler fails after forking
Message-ID:  <200102151104.f1FB4Je93428@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         25110
>Category:       bin
>Synopsis:       pthread signal handler fails after forking
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Feb 15 03:10:01 PST 2001
>Closed-Date:
>Last-Modified:
>Originator:     Kazunori Ueno
>Release:        4.2-RELEASE
>Organization:
Univ. of Tokyo
>Environment:
FreeBSD KitzBSD.chem.t.u-tokyo.ac.jp 4.2-RELEASE FreeBSD 4.2-RELEASE #1: Mon Jan 15 20:14:10 JST 2001     root@KitzBSD.chem.t.u-tokyo.ac.jp:/usr/src/sys/compile/KitzBSD  i386
>Description:
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.


>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;
}


>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.



>Release-Note:
>Audit-Trail:
>Unformatted:


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200102151104.f1FB4Je93428>