Ton*_*vel 6 c++ boost boost-process
根据Boost文档("管道为什么不关闭?"部分),以下代码将导致死锁:
#include <boost/process.hpp>
#include <iostream>
namespace bp = ::boost::process;
int main(void)
{
bp::ipstream is;
bp::child c("ls", bp::std_out > is);
std::string line;
while (std::getline(is, line))
{
std::cout << line << "\n";
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
文件说:
这也会死锁,因为子进程退出时管道不会关闭.因此,即使进程已经结束,ipstream仍将查找数据.
但是,我无法重现死锁(在Linux下).此外,我不明白为什么首先会发生僵局.子进程退出后,它会关闭管道的写入端.管道的读取端仍然可供父进程读取,并且std::getline()一旦管道缓冲区中没有更多数据可用就会失败,并且写入端已关闭,对吗?如果在执行子进程期间管道缓冲区填满,子进程将阻止等待父进程从管道读取足够的数据,以便它可以继续.
因此,如果上面的代码可以死锁,有没有一种简单的方法来重现死锁场景?
更新:
实际上,使用Boost进程的下面一段代码死锁:
#include <boost/process.hpp>
#include <iostream>
namespace bp = ::boost::process;
int main()
{
bp::ipstream is;
bp::child c("/bin/bash", bp::args({"-c", "ls >&40"}), bp::posix::fd.bind(40, is.rdbuf()->pipe().native_sink()));
std::string line;
while (std::getline(is, line))
{
std::cout << line << "\n";
}
c.wait();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我想知道这是否真的是Linux下进程产生的一些不可避免的属性.使用Facebook的Folly库中的Subprocess重现上面的例子至少不会死锁:
#include <folly/Subprocess.h>
#include <iostream>
int main()
{
std::vector<std::string> arguments = {"/bin/bash", "-c", "ls >&40"};
folly::Subprocess::Options options;
options.fd(40, STDOUT_FILENO);
folly::Subprocess p(arguments, options);
std::cout << p.communicate().first;
p.wait();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
\n\n\n一旦子进程退出,它就会关闭管道的写端。
\n
这似乎是假设。什么程序关闭什么管道?
\n\n如果/bin/ls是的话,会发生什么
bp::child c("/bin/bash", bp::args({"-c", "ls; ls"}));\nRun Code Online (Sandbox Code Playgroud)\n\n如果ls真的关闭的话,应该关闭两次。
也许 bash 在引擎盖下复制了句柄,因此子进程关闭不同的同一管道的我不确定这些语义的可靠性\xc2\xb9
\n\n因此,显然 stdout 得到了很好的满足。但是,在 Linux 上使用非标准文件描述符进行输出时,我可以重现死锁:
\n\n#include <boost/process.hpp>\n#include <iostream>\n\nnamespace bp = ::boost::process;\n\nint main() {\n bp::ipstream is;\n bp::child c("/bin/bash", bp::args({"-c", "exec >&40; ls"}), bp::posix::fd.bind(40, is.rdbuf()->pipe().native_sink()));\n\n std::string line;\n while (std::getline(is, line)) {\n std::cout << line << "\\n";\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n我不确定为什么 bash 中的子进程的“关闭标准输出”行为在重定向到 fd 时应该表现不同,但就是这样。
\n\n演示相关死锁的另一种好方法是:
\n\n{\n bp::child c("/bin/bash", bp::args({"-c", "ls -R /"}), bp::std_out > is);\n c.wait();\n return c.exit_code();\n}\nRun Code Online (Sandbox Code Playgroud)\n\n这个答案不是结论性的,但确实观察到了一些要点并在 Linux 上进行了演示:
\n\n我认为后者是文档中的重点。
\n\n\xc2\xb9 实际上,文档明确表明这些语义的差异是 Win32 中的问题:
\n\n\n\n在此库中不可能使用自动管道关闭,因为管道可能是文件句柄(对于 Windows 上的异步管道)
\n
| 归档时间: |
|
| 查看次数: |
336 次 |
| 最近记录: |