来自man -e 2 wait
:
呼叫等待(&status)等效于: waitpid(-1,&status,0);
errno值:
未设置EINTR WNOHANG,并且设置了无阻塞信号或SIGCHLD 抓住;参见signal(7)。
因此,根据我的理解,如果我们在“等待”中受阻并收到信号(SIGCHLD),则调用应以-1并将errno设置为EINTR的方式返回。 尽管运行以下代码片段将证明等待实际上已经重新启动(Linux 4.15.0-43,glibc 2.23):
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
static void sigchld_handler(int signo)
{
const char *const msg = "\nSIGCHLD";
(void)signo;
write(STDERR_FILENO, msg, strlen(msg));
}
int main(void)
{
pid_t wait_ret = 0, pid = 0;
int status = 0, ret = -1;
sigaction(SIGCHLD, &(struct sigaction){
.sa_handler = sigchld_handler,
}, NULL);
if ((pid = fork()) < 0)
{
perror("\nfork: ");
goto Exit;
}
if (!pid)
{
sleep(3);
return 0;
}
if ((wait_ret = wait(&status)) < 0)
{
perror("\nwait: ");
goto Exit;
}
fprintf(stderr, "\nwait done, pid %d", wait_ret);
ret = 0;
Exit:
fprintf(stderr, "\n");
return ret;
}
未设置SA_RESTART-为什么“等待”重新启动? 实际输出:
SIGCHLD wait done, pid 15242
由我期望的输出:
SIGCHLD wait: Interrupted system call
从shell手动注意kill -CHLD <waiting process>
将得到预期的结果。
还请注意,在FreeBSD 11.2上运行代码也将获得预期的结果-等待在子退出时因错误而中断。
答案 0 :(得分:3)
这里的解释很微妙。您必须先开始:
成功后,[
wait
]返回终止子进程的进程ID;如果出错,则返回-1。
关于errno
值的文档需要这样解释: 如果wait()
返回-1 ,则表示错误,并且errno
设置为EINTR
,则解释为SIGCHLD
或不受阻碍的(其他)信号中断了等待。但这并不意味着接收SIGCHLD
一定会导致wait()
失败。特别是,wait()
将正常完成,而不是SIGCHLD
是由于某个进程的子进程的终止而引起的错误。
在对此处的文档过于批评之前,请考虑一下
SIGCHLD
可能由于孩子被终止以外的其他原因而分娩SIGCHLD
可能会被一些他们不等待的孩子打断。文档的措辞似乎也暗示SIGCHLD
可能导致其中一个或多个功能因EINTR
而失败,即使该信号被阻止。我会发现这种行为令人惊讶,但请记住我是从哪里开始的:该结果是对EINTR
错误的可能解释之一,并不一定意味着它实际上可能发生。