使用信号捕获fork时程序无限

时间:2013-03-23 12:21:36

标签: linux unix operating-system signals fork

每个人,在使用fork和signal进行一些实验的同时,我遇到了一个显示非常有趣的行为的程序,但经过几个小时的努力,我无法弄清楚发生了什么。

我想要做的是我在主体内部创建一个子进程,然后打印“hello world”然后调用exit。在此之后,完全可以理解它的信号处理程序将被调用,并且还会调用被wait系统调用阻塞的父进程。现在我在信号处理程序中创建另一个进程,但从那里开始,输出变为无限。

输出是这样的: 你好,世界 来到Linux来UNIX运行Linux来UNIX运行Linux来UNIX ...

为什么一次又一次地打印Linux。

另外请告诉我什么时候调用fork,我知道重复的地址空间是由父节点组成的,但是信号处理程序呢。他们也得到重复。在我的情况下,当孩子呼叫退出。然后被调用的信号处理程序是子或父。

请帮忙。 感谢。

void sig_handler(int signo)
{
if(fork() == 0){

}
else{
    int pid = 0;
    wait(&pid);
    printf("Come to unix");
    fflush(stdout);
}
 }


int main()
{
if (signal(SIGCHLD, sig_handler) == SIG_ERR){
}

int child_pid;
int i;

child_pid = fork();
switch (child_pid) {
    case -1:         
        perror("fork");
        exit(1);
    case 0:          
        printf("hello world\n");fflush(stdout);        
        exit(0);
    default:
        wait(&i);
        printf("Come to linux");
        exit(0);
        //break;
}

return 0;
}

2 个答案:

答案 0 :(得分:1)

它是否会进入无限循环并不明显?您已经创建了一个SIGCHLD处理程序,然后在该处理程序中再次分叉并等待子进程退出。基本上当处理程序中的子进程再次进入父进程时,进入处理程序。 以下代码应该避免它。在信号处理程序开始时,通过将其设置为默认值来避免信号。

void sig_handler(int signo) {
     signal (SIGCHLD, SIG_IGN);
    if(fork() == 0){ 

    }   
    else{
        int pid = 0;
        wait(&pid);
        printf("Come to unix");
        fflush(stdout);
    }    
}

此外,您只能在信号处理程序中调用异步信号安全例程以避免未定义的行为。我不确定printf和fflush是否同步安全。即使进行上述更改避免了循环,程序仍可能具有未定义的行为。 我猜fork是异步安全的

请参阅以下可能有用的讨论: http://sourceware.org/bugzilla/show_bug.cgi?id=4737

答案 1 :(得分:0)

根据POSIX标准,在信号处理程序中调用fork(2)具有未定义的行为,所以不要这样做:)

请参阅:http://pubs.opengroup.org/onlinepubs/009695399/functions/fork.html