在以下情况下如何避免read()挂起? [英] How to avoid read() from hanging in the following situation?

查看:149
本文介绍了在以下情况下如何避免read()挂起?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些代码可以派生第三方应用程序,并将其标准输出重定向到父进程,大致如下(为简洁起见,此处没有错误处理):

I have some code that forks a third-party application and redirects its standard output to the parent process, roughly as follows (no error handling here for brevity):

char* args[] = {"/path/to/3rd/party/binary", "with", "args", NULL};

int fds[2];
pipe2(fds, O_CLOEXEC);

pid_t pid = fork();
if (pid == 0)
{
    dup2(fds[1], STDOUT_FILENO);
    execvp(args[0], args);
    _exit(1);
}
else
{
    close(fds[1]);

    char buf[1024];
    int bytes_read;
    while ((bytes_read = read(fds[0], buf, sizeof buf - 1)) > 0)
    {
        buf[bytes_read] = '\0';
        printf("%s", buf);
    }

    close(fds[0]);
    waitpid(pid, NULL, 0);
}

我没有第三方应用程序的代码,它是专有的二进制文件.当在终端中使用与上面的代码相同的参数运行第三方应用程序时,最终将完成.但是,使用上面的代码分叉第三方二进制文件时,它并没有完成,而是变成了僵尸进程,并且上面的代码挂在了read()调用上.

I have no code for the third-party application, it is a proprietary binary. When running the third-party application in a terminal with the same arguments as used in the code above, it eventually finishes. However, when forking the third-party binary using the code above, it does not finish, but becomes a zombie process, and the code above hangs on the read() call.

自身分叉的第三方二进制文件分叉了两个守护进程(同样,我不控制的专有二进制文件),我认为这是造成此问题的原因.分叉的守护程序进程将具有重复文件描述符的副本,从而阻止read()完成.的确,如果dup2()调用被替换为:

The third-party binary that is forked itself forks two daemon processes (again, proprietary binaries I do not control), which I think is causing the problem here. The forked daemon processes will have a copy of the duplicated file descriptor, preventing the read() from finishing. Indeed, in case the dup2() call is replaced with:

dup3(fds[1], STDOUT_FILENO, O_CLOEXEC);

子进程完成,但是没有输出重定向到父进程.另外,如果将上面的代码修改为不通过管道将任何输出重定向到父级,则子级进程将正确完成.

the child process finishes, but there is no output redirection to the parent process of course. Also, when the code above is modified to not do any output redirection to the parent over a pipe, the child process finishes correctly.

在这种情况下是否可以通过某种方式防止在read()调用上挂起,还是我需要诉诸某种形式的非阻塞I/O?

Is it possible to somehow prevent this hang on the read() call in this situation, or do I need to resort to some form of non-blocking I/O?

更新;使用简单的popen()会遇到相同的问题.

Update; using a simple popen() suffers from the same problem.

(后续行动来自: read()挂在僵尸进程上)

推荐答案

您需要专门忽略SIGCHLD.获得僵尸是您的责任,但是在read中被阻止时您将无法做.如果吞下SIGCHLD后再呼叫read,您将永远留在read中.

You need to specifically ignore SIGCHLD. It's your responsibility to reap the zombie, but you can't do it when blocked in read. If you call read after the SIGCHLD has been swallowed, you'll stay in read forever.

这篇关于在以下情况下如何避免read()挂起?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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