gpt4 book ai didi

c++ - 强制文件描述符关闭以便 pclose() 不会阻塞的方法?

转载 作者:行者123 更新时间:2023-11-30 02:57:46 27 4
gpt4 key购买 nike

我正在使用 popen() 创建一个管道,并且该过程正在调用第三方工具,在极少数情况下我需要终止该工具。

::popen(thirdPartyCommand.c_str(), "w");

如果我只是抛出一个异常并展开堆栈,我的展开会尝试在我不再需要其结果的第三方进程上调用 pclose()。但是,pclose() 永远不会返回,因为它会在 Centos 4 上阻塞并使用以下堆栈跟踪:

#0  0xffffe410 in __kernel_vsyscall ()
#1 0x00807dc3 in __waitpid_nocancel () from /lib/libc.so.6
#2 0x007d0abe in _IO_proc_close@@GLIBC_2.1 () from /lib/libc.so.6
#3 0x007daf38 in _IO_new_file_close_it () from /lib/libc.so.6
#4 0x007cec6e in fclose@@GLIBC_2.1 () from /lib/libc.so.6
#5 0x007d6cfd in pclose@@GLIBC_2.1 () from /lib/libc.so.6

有什么方法可以在调用它之前强制调用 pclose() 成功,这样我就可以通过编程避免我的进程挂起等待 pclose() 成功的情况,而它永远不会成功,因为我已经停止了向 popen()ed 进程提供输入并希望丢弃它的工作?

在尝试关闭它之前,我是否应该以某种方式将文件结尾写入 popen()ed 文件描述符?

请注意,第三方软件正在 fork 自身。在 pclose() 挂起的位置,有四个进程,其中一个已失效:

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
abc 6870 0.0 0.0 8696 972 ? S 04:39 0:00 sh -c /usr/local/bin/third_party /home/arg1 /home/arg2 2>&1
abc 6871 0.0 0.0 10172 4296 ? S 04:39 0:00 /usr/local/bin/third_party /home/arg1 /home/arg2
abc 6874 99.8 0.0 10180 1604 ? R 04:39 141:44 /usr/local/bin/third_party /home/arg1 /home/arg2
abc 6875 0.0 0.0 0 0 ? Z 04:39 0:00 [third_party] <defunct>

最佳答案

我在这里看到两个解决方案:

  • 简洁的:你 fork()pipe()execve()(或 exec family 当然...)“手动”,然后由您决定是否要让您的 child 变成僵尸。 (即是否为他们 wait())
  • 丑陋的:如果你确定在任何给定时间你只有一个这个子进程在运行,你可以使用 sysctl() 来检查是否有任何进程正在运行这个名称在调用 pclose() 之前... yuk

我在这里强烈建议采用简洁的方法,或者您可以请负责人在您的第三方工具中修复该无限循环哈哈。

祝你好运!

编辑:

第一个问题:我不知道。对如何使用 sysctl() 按名称查找进程进行一些研究应该会告诉您您需要了解的内容,我自己从未将其推进到这种程度。

对于你的第二个和第三个问题:popen() 基本上是 fork() + pipe()< 的包装器 + dup2() + execl().

fork() 复制进程,execl() 用新的图像替换复制的进程图像,pipe() 处理内部进程通信和 dup2() 用于重定向输出...然后 pclose()wait() 用于重复的进程死,这就是我们在这里的原因。

如果你想了解更多,你应该检查this answer我最近在其中解释了如何使用标准 IPC 执行简单的 fork 。在这种情况下,它只是有点复杂,因为您必须使用 dup2() 将标准输出重定向到您的管道。

您还应该查看 popen()/pclose() 源代码,因为它们当然是开源的。

最后,这是一个简短的例子,我再清楚不过了:

int    pipefd[2];

pipe(pipefd);
if (fork() == 0) // I'm the child
{
close(pipefd[0]); // I'm not going to read from this pipe
dup2(pipefd[1], 1); // redirect standard output to the pipe
close(pipefd[1]); // it has been duplicated, close it as we don't need it anymore
execve()/execl()/execsomething()... // execute the program you want
}
else // I'm the parent
{
close(pipefd[1]); // I'm not going to write to this pipe
while (read(pipefd[0], &buf, 1) > 0) // read while EOF
write(1, &buf, 1);
close(pipefd[1]); // cleaning
}

和往常一样,记得阅读手册页并检查所有返回值。

再次祝你好运!

关于c++ - 强制文件描述符关闭以便 pclose() 不会阻塞的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14183572/

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