我有一个简单的 C++ 应用程序,它应该从 POSIX 命名管道读取行:
#include<iostream>
#include<string>
#include<fstream>
int main() {
std::ifstream pipe;
pipe.open("in");
std::string line;
while (true) {
std::getline(pipe, line);
if (pipe.eof()) {
break;
}
std::cout << line << std::endl;
}
}
Steps:
sleep infinity > in & # keep pipe open, avoid EOF
echo hey > in
echo cats > in
echo foo > in
kill %1 # this closes the pipe, C++ app stops on EOF
在 Linux 下执行此操作时,应用程序在每次之后成功显示输出echo
命令如预期(g++ 8.2.1)。
在 macOS 上尝试整个过程时,仅在关闭管道后(即在kill %1
)。
我开始怀疑某种缓冲问题,所以我尝试像这样禁用它:
std::ifstream pipe;
pipe.rdbuf()->pubsetbuf(0, 0);
pipe.open("out");
通过此更改,应用程序在第一个之后不会输出任何内容echo
,然后打印第二条消息后的第一条消息echo
(“嘿”),并继续这样做,总是落后一条消息并显示上一条消息echo
而不是被处决的人。
最后一条消息仅在关闭管道后显示。
我发现在 macOS 上g++
基本上是clang++
, as
g++ --version
产生:“Apple LLVM 版本 10.0.1 (clang-1001.0.46.3)”。
使用 Homebrew 安装真正的 g++ 后,示例程序可以正常工作,就像在 Linux 上一样。
由于各种原因,我正在构建一个基于命名管道的简单 IPC 库,因此此时正确工作对我来说几乎是一个要求。
What is causing this weird behaviour when using LLVM? (update: this is caused by libc++)
这是一个错误吗?
C++ 标准是否以某种方式保证了 g++ 上的工作方式?
我怎样才能使这个代码片段正常工作clang++
?
Update:
这似乎是由 libc++ 实现引起的getline()
。
相关链接:
- 为什么从管道读取时 libc++ getline 会阻塞,而 libstdc++ getline 不会? https://stackoverflow.com/questions/47192984/why-does-libc-getline-block-when-reading-from-pipe-but-libstdc-getline-does
- https://bugs.llvm.org/show_bug.cgi?id=23078 https://bugs.llvm.org/show_bug.cgi?id=23078
但问题仍然存在。