【发布时间】:2015-03-27 23:45:40
【问题描述】:
我正在尝试编写一个程序,在该程序中,我从父母那里分叉出一个孩子,并使用处理程序处理 SIGCHLD 信号,其中我使用了 waitpid()。但是,当我执行它时,有时我会从 waitpid 获得返回值 0,同时将 errno 设置为 EINTR。这是什么意思?
这是我的 SIGCHLD 处理程序:
pid_t pid;
int status;
while((pid = waitpid(-1, &status, WNOHANG|WUNTRACED)) > 0)
{
printf("Handler reaped child %d\n", (int)pid);
if(WIFEXITED(status))
{
deletejob(job_list, pid);
}
else if(WIFSIGNALED(status))
{
deletejob(job_list, pid);
}
else if(WIFSTOPPED(status))
{
struct job_t *job = getjobpid(job_list, pid);
job->state = ST;
}
}
printf("%d %d\n", pid, errno);
if(errno != ECHILD)
{
unix_error("waitpid error");
}
return;
这是父函数,我在其中 fork 子函数:
pid_t pid;
sigset_t block_set;
int file_descriptor;
if(tok.outfile == NULL)
{
file_descriptor = STDOUT_FILENO;
}
else
{
file_descriptor = open(tok.outfile, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
}
sigemptyset(&block_set);
sigaddset(&block_set, SIGCHLD);
sigaddset(&block_set, SIGINT);
sigaddset(&block_set, SIGTSTP);
sigprocmask(SIG_BLOCK, &block_set, NULL);
pid = fork();
if(pid == 0)
{
sigprocmask(SIG_UNBLOCK, &block_set, NULL);
setpgid(0, 0);
dup2(file_descriptor, 1);
while(execve(tok.argv[0], tok.argv, environ) < 0)
{
exit(0);
}
}
else
{
if(bg == 1)
{
addjob(job_list, pid, BG, cmdline);
sigprocmask(SIG_UNBLOCK, &block_set, NULL);
int jid = pid2jid(pid);
printf("[%d] (%d) %s\n", jid, pid, cmdline);
}
else if(bg == 0)
{
addjob(job_list, pid, FG, cmdline);
sigprocmask(SIG_UNBLOCK, &block_set, NULL);
}
if(bg == 0)
{
struct job_t *job = getjobpid(job_list, pid);
while(pid == fgpid(job_list))
{
sleep(1);
}
}
}
}
return;
【问题讨论】:
-
waitpid()如果指定WNOHANG,则在没有准备好收割的子进程时返回 0。由于它没有返回错误,因此您不应该检查errno。其他一些系统调用必须在之前被中断,然后设置它。 -
好的。知道了。那么有什么方法可以检查哪个系统调用的中断设置了errno呢?
-
是的,通过检查每个系统调用的返回值,并检查
errno是否有任何返回错误。 -
好的。我会去做的。谢谢您的帮助!!顺便说一句,删除检查 errno 解决了所述问题。
-
EINTR可能发生在某个库函数中,不一定发生在您的直接系统调用之一中。一般来说,您应该忽略errno,除非您刚刚进行了报告错误的系统调用。