0

我正在尝试学习如何处理信号。在我的程序中,我有一组早期创建的子进程的 pid。不,我想每隔几秒钟向其中一个发送一个 sigtstp 信号。他只需要将 sigchld 发送到父进程并退出。父进程应该打印退出进程的退出代码并创建下一个来代替退出一。在第一个循环中一切正常,但在第二个循环中挂起。所以输出得到:

loop
slept
forking
in to array
loop
Zakonczyl sie potomek 3934 z kodem 0.

因此,睡眠似乎在第一个循环中有效,但在第二个循环中无效。或者只是主进程在处理信号后没有重新获得控制权,但这不应该发生。所以我不知道这里可能有什么问题。

while(1) {
                printf("loop\n");
                sleep(5);
                printf("slept\n");
                int r = rand() % n;
                if(kill(process_tab[r],SIGTSTP) < 0) {
                        printf("Error while sending sigtstp signal.\n");
                } else {
                        printf("forking\n");
                        if((child = fork()) < 0) {
                                printf("Fork failed.\n");
                        } else if(child == 0) {//to sie dzieje w procesie
                                if(signal(SIGTSTP,&catch_sigtstp)) {
                                        printf("Error while setting signal handler.\n");
                                        _exit(EXIT_FAILURE);
                                }
                                while(1) {
                                }
                        } else { //to sie dzieje w parencie
                                process_tab[r] = child;
                                printf("in to array\n");
                        }
                }
}

这里是处理程序。

void catch_sigtstp(int signal) {
        kill(ppid,SIGCHLD);
        _exit(EXIT_SUCCESS);
}

void catch_sigchld (int signal) {
        int status;
        pid_t child = wait(&status);
        printf("Zakonczyl sie potomek %d z kodem %d.\n",child,status);
}
4

1 回答 1

2

fflush之后添加printf

printf("Something\n");
fflush(stdout);

否则,您可能无法获得stdio默认缓冲的输出。

编辑:处理程序的问题

在信号处理程序中使用函数是非常不安全的printf,因为它不可重入。此外,catch_sigchild还可以修改函数:

void catch_sigchld (int signal) {
    int status;
    pid_t child;

    while ((child = waitpid(-1, &status, WNOHANG)) > 0)
    {
       // may be something else?
       // ...printf("Zakonczyl sie potomek %d z kodem %d.\n",child,status); 
    }
}   

原因是可以为多个死去的孩子传递一个信号。

编辑:打印时阻塞信号。

为避免 stdio 内部出现死锁,您应该阻止该信号:

sigset_t set;

sigemptyset(&set);
sigaddset(&set, SIGCHILD);

...
sigprocmask(SIG_BLOCK, &set, NULL);
printf("my output");
sigprocmask(SIG_UNBLOCK, &set, NULL);
...

编辑:正如@Barmar 所指出的,您的父进程将收到两次 SIGCHILD 信号:一次来自您孩子的信号处理程序,一次来自操作系统。

要修复,删除您自己的信号源可能就足够了:

void catch_sigtstp(int signal) {
    // kill(ppid,SIGCHLD); //< This one causes two signals per one child
    _exit(EXIT_SUCCESS);
}
于 2013-05-02T19:52:58.033 回答