Я использую shell-подобную программу на С++. Он имеет петлю, которая читает из cin, forks и ждет ребенка.
Это отлично работает, если вход является интерактивным или если он передан из другой программы. Однако, когда вход является bash heredoc, программа перечитывает части ввода (иногда неопределенно).
Я понимаю, что дочерний процесс наследует дескрипторы родительского файла, включая смещение общего файла. Тем не менее, ребенок в этом примере ничего не читает из cin, поэтому я думаю, что он не должен касаться смещения. Я как бы зациклен на том, почему это происходит.
test.cpp:
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, char **argv)
{
std::string line;
while (std::getline(std::cin, line)) {
pid_t pid = fork();
if (pid == 0) { // child
break; // exit immediately
}
else if (pid > 0) { // parent
waitpid(pid, nullptr, 0);
}
else { // error
perror("fork");
}
std::cout << getpid() << ": " << line << "\n";
}
return 0;
}
Я скомпилирую его следующим образом:
g++ test.cpp -std=c++11
Затем я запускаю его с помощью:
./a.out <<EOF
hello world
goodbye world
EOF
Вывод:
7754: hello world
7754: goodbye world
7754: goodbye world
Если я добавлю третью строку foo bar
во входную команду, программа застрянет в бесконечном цикле:
13080: hello world
13080: goodbye world
13080: foo bar
13080: o world
13080: goodbye world
13080: foo bar
13080: o world
[...]
Версии:
- Ядро Linux: 4.4.0-51-generic
- Ubuntu: 16.04.1 LTS (xenial)
- bash: GNU bash, версия 4.3.46 (1) -release (x86_64-pc-linux-gnu)
- gcc: g++ (Ubuntu 5.4.0-6ubuntu1 ~ 16.04.4) 5.4.0 20160609