gpt4 book ai didi

c - waitpid() 返回值 0 以及 errno EINTR

转载 作者:太空宇宙 更新时间:2023-11-04 01:27:05 24 4
gpt4 key购买 nike

我正在尝试编写一个程序,在该程序中我从父进程中 fork 出一个子进程,并使用一个处理程序处理 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;

最佳答案

当用 WNOHANG 调用时, waitpid()返回 0当没有更多的 child 留下来收割时。你的SIGCHLD handler 在子进程退出时被调用,所以你知道总会有至少一个要收割。但是因为多个信号不会排队,所以可能会有不止一个子进程要获取。

这又是什么while循环做:

while((pid = waitpid(-1, &status, WNOHANG|WUNTRACED)) > 0)

基本上是说“调用 waitpid() 获取我知道正在等待的 child ,然后一遍又一遍地调用它以获取可能碰巧可用的任何其他 child ,直到它返回 0,此时我知道我已经收获了所有可用的 child 。”

返回 0因此,这不是一个错误,这是一个蓄意收割未知数量 child 的装置。 waitpid()没有设置 errno ,在这种情况下,所以 EINTR必须在某些先前的系统调用被中断时设置。

一般来说,你不应该检查errno除非一个函数返回一个错误,尽管有一些不寻常的情况( strtol() 是一个,返回 0 可能意味着解析的数字是 0 ,或者可能意味着有错误)返回值不会明确指示错误。在这些情况下,您可以设置 errno0在调用该函数之前,如果返回值提示可能有错误,您可以检查errno查看它是否已设置。

关于c - waitpid() 返回值 0 以及 errno EINTR,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29311920/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com