In C++, calling fork when cin is a bash heredoc causes repeated input fragments
<p>I am implementing a shell-like program in C++. It has a loop that reads from cin, forks, and waits for the child.</p>

<p>This works fine if the input is interactive or if it's piped from another program. However, when the input is a <a href="http://www.tldp.org/LDP/abs/html/here-docs.html" rel="noreferrer">bash heredoc</a>, the program rereads parts of the input (sometimes indefinitely).</p>

<p>I understand that the child process inherits the parent's file descriptors, including shared file offset. However, the child in this example does not read anything from cin, so I think it shouldn't touch the offset. I'm kind of stumped about why this is happening.</p>

<hr>

<p>test.cpp:</p>

<pre><code>#include &lt;iostream&gt;
#include &lt;unistd.h&gt;
#include &lt;sys/wait.h&gt;

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 &gt; 0) { // parent
            waitpid(pid, nullptr, 0);
        }
        else { // error
            perror("fork");
        }

        std::cout &lt;&lt; getpid() &lt;&lt; ": " &lt;&lt; line &lt;&lt; "\n";
    }
    return 0;
}
</code></pre>

<p>I compile it as follows:</p>

<pre><code>g++ test.cpp -std=c++11
</code></pre>

<p>Then I run it with:</p>

<pre><code>./a.out &lt;&lt;EOF
hello world
goodbye world
EOF
</code></pre>

<p>Output:</p>

<pre><code>7754: hello world
7754: goodbye world
7754: goodbye world
</code></pre>

<p>If I add a third line <code>foo bar</code> to the input command, the program gets stuck in an infinite loop:</p>

<pre><code>13080: hello world
13080: goodbye world
13080: foo bar
13080: o world
13080: goodbye world
13080: foo bar
13080: o world
[...]
</code></pre>

<hr>

<p>Versions:</p>

<ul>
<li>Linux kernel: 4.4.0-51-generic</li>
<li>Ubuntu: 16.04.1 LTS (xenial)</li>
<li>bash: GNU bash, version 4.3.46(1)-release (x86_64-pc-linux-gnu)</li>
<li>gcc: g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609</li>
</ul>