У меня есть простое приложение 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;
}
}
шаги:
-
Я создаю именованный канал:
mkfifo in
. -
Я компилирую и запускаю код C++, используя
g++ -std=C++11 test.cpp &&./a.out
. -
Я передаю данные
in
трубу:
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++
, так как g++ --version
выдает: "Apple LLVM версия 10.0.1 (clang-1001.0.46.3)". После установки настоящего g++ с использованием Homebrew, пример программы работает так же, как и в Linux.
Я строю простую библиотеку IPC, построенную на именованных каналах по разным причинам, поэтому правильная работа с ней в значительной степени является требованием для меня на данный момент.
Что вызывает это странное поведение при использовании LLVM? (обновление: это вызвано lib C++)
Это ошибка?
Каким-то образом гарантируется, как это работает на g++ стандартом C++?
Как я могу заставить этот фрагмент кода работать должным образом, используя clang++
?
Обновить:
По-видимому, это вызвано реализацией lib C++ функции getline()
. Ссылки по теме:
- Почему lib C++ getline блокируется при чтении из канала, а libstd C++ getline - нет?
- https://bugs.llvm.org/show_bug.cgi?id=23078
Вопросы все еще стоят, хотя.