【发布时间】:2014-02-11 05:09:05
【问题描述】:
我正在为一个工具包编写一个模块,该模块需要执行一些子进程并读取它们的输出。但是,使用该工具包的主程序也可能会产生一些子进程并为SIGCHLD 设置一个信号处理程序,该处理程序调用wait(NULL) 以摆脱僵尸进程。因此,如果我在waitpid() 中创建的子进程退出,则在调用信号处理程序之前处理子进程,因此信号处理程序中的wait() 将等待下一个进程结束(这可能需要曾经)。这种行为在the man page of waitpid(参见被授予者2)中有所描述,因为linux 实现似乎不允许wait() 系列处理SIGCHLD。我试过popen() 和posix_spawn(),他们都有同样的问题。我也尝试使用双重fork(),以便直接子立即存在,但我仍然无法保证在收到SIGCHLD 后调用waitpid()。
我的问题是,如果程序的其他部分设置了一个调用wait() 的信号处理程序(也许它应该调用waidpid,但这不是我可以控制的),有没有办法安全地执行 child进程而不覆盖 SIGCHLD 处理程序(因为它可能在某些程序中有用)或任何僵尸进程。
一个显示问题的小程序在这里(请注意,主程序仅在长期子退出后退出,而不是使用waitpid()直接等待的短程序):
#include <signal.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
static void
signalHandler(int sig)
{
printf("%s: %d\n", __func__, sig);
int status;
int ret = waitpid(-1, &status, 0);
printf("%s, ret: %d, status: %d\n", __func__, ret, status);
}
int
main()
{
struct sigaction sig_act;
memset(&sig_act, 0, sizeof(sig_act));
sig_act.sa_handler = signalHandler;
sigaction(SIGCHLD, &sig_act, NULL);
if (!fork()) {
sleep(20);
printf("%s: long run child %d exit.\n", __func__, getpid());
_exit(0);
}
pid_t pid = fork();
if (!pid) {
sleep(4);
printf("%s: %d exit.\n", __func__, getpid());
_exit(0);
}
printf("%s: %d -> %d\n", __func__, getpid(), pid);
sleep(1);
printf("%s, start waiting for %d\n", __func__, pid);
int status;
int ret = waitpid(pid, &status, 0);
printf("%s, ret: %d, pid: %d, status: %d\n", __func__, ret, pid, status);
return 0;
}
【问题讨论】:
标签: linux fork waitpid sigchld