前叉+等待在OSX上获得EINTR [英] fork + wait gets EINTR on OSX

查看:85
本文介绍了前叉+等待在OSX上获得EINTR的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在派生101处失败.我希望它派生一个子进程,并输出子和父printfs:

I fail at fork 101. I expect this to fork a child process, and output both child and parent printfs:

pid_t fpid;

if ((fpid = fork()) < 0)
{
    printf("fork: %s\n", strerror(errno));
    exit(-1);
}

if (0 == fpid) // child
{
    printf("\nI am the child\n");
}
else
{
    printf("\nI am the parent\n");
    pid_t wpid;
    while ((wpid = waitpid(WAIT_ANY, NULL, 0)))
    {
        if (errno == ECHILD)
            break;
        else if (wpid < 0)
            printf("wait: %s\n", strerror(errno));
    }
}

相反,我得到以下输出:

Instead, I get this output:

我是父母

等待:系统调用中断

所以我的问题是:为什么孩子没有生活和奔跑的机会?没人会想起孩子们!另外,EINTR来自何处?显然,这与我的第一个问题有关.

So my question is: why doesn't the child get a chance to live and run? Won't someone please think of the children! Also, where does the EINTR come from? Obviously, this is somehow related to my first question.

此外,当我在独立程序中运行该代码时,它可以正常工作,但在我的较大程序中时却无法正常工作;较大的程序可以做什么来使waitpid感到不安?

Furthermore, when I run that code in a standalone program, it works correctly, but not when inside a larger program of mine; what could the larger program do to upset waitpid?

FWIW,这是在OSX 10.9上.

FWIW this is on OSX 10.9.

推荐答案

在OSX上,在执行前/不执行前,在fork的子级执行大量操作是不合法的.请参阅 fork底部的警告手册页.安全功能列表位于 sigaction (2)手册页. printf()不在其中.

On OSX, it's not legal to do much on the child side of a fork before/without execing. See the caveat at the bottom of the fork man page. The list of safe functions is on the sigaction(2) man page. printf() is not among them.

此外,stdout可能已被缓冲. printf()的结果可能未刷新.如果您调用exit(),它将被刷新,但这在fork的子端也不合法. (使用_exit()是适当的,但是它不会刷新打开的流.)确实,您似乎没有退出子进程,这意味着执行流将继续显示给您所显示的代码的调用者,大概返回到程序的其余部分.由于叉子侧的限制,它可能会卡在那里.

Also, stdout is likely buffered. The results of the printf() may not be being flushed. It would be flushed if you called exit(), but that's also not legal on the child side of a fork. (It's appropriate to use _exit() but that doesn't flush open streams.) As it is, you don't appear to be exiting your child process, which means flow of execution continues to the caller of the code you've shown, presumably returning to the rest of your program. It may be getting stuck there because of the limitations on the child side of a fork.

如果您在孩子中做这样的事情,您可能会有更多的运气:

You may have more luck if you do something like this in the child:

const char msg[] = "\nI am the child\n";
write(STDOUT_FILENO, msg, sizeof(msg) - 1);
_exit(0);

最后,我认为您应该将fpid而不是WAIT_ANY传递给waitpid().您有一个要等待的特定子进程.在更大的程序中,您不想窃取由其他子组件产生的子项终止的通知.而且,您始终需要循环访问可中断的系统调用,直到它们返回除EINTR之外的其他值.

Finally, I think you should pass fpid rather than WAIT_ANY to waitpid(). You have a specific child process you want to wait for. In the context of a larger program, you don't want to steal the notification of the termination of a child spawned by some other subcomponent. And you always need to loop around interruptible syscalls until they return something other than EINTR.

这篇关于前叉+等待在OSX上获得EINTR的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆