Re: 12.2: fork() causing getline() to repeat stdin endlessly
On Mon, Oct 23, 2023 at 11:15:22AM +0200, Thomas Schmitt wrote:
> it helps to do
> fflush((stdout);
> after each printf(), or to run before the loop:
> setvbuf(stdout, NULL, _IONBF, 0);
>
> So it is obvious that the usual output buffering of printf() causes the
> repetitions of text.
Yes, it looks like a buffering issue to me as well. Or, more generally,
some kind of weird interaction between buffered stdio FILEs and the
underlying Unix file descriptors, when new processes are being fork()ed.
> The loop does not do any extra cycles, as i could confirm by inserting
Here's another interesting observation: using the original program with
only the argc/argv change, there is different behavior depending on
whether stdin points to a file, or a pipe.
unicorn:~$ seq 1 2 | ./foo
1
num_read: 2 at line 1
2
num_read: 2 at line 2
unicorn:~$ seq 1 2 > bar
unicorn:~$ ./foo < bar
1
num_read: 2 at line 1
2
num_read: 2 at line 2
2
num_read: 2 at line 3
unicorn:~$
Clearly there are different mechanisms in play based on whether stdin is
a regular file or a pipe. I can't fully explain this result, though.
On Mon, Oct 23, 2023 at 12:59:38AM -0400, tom kronmiller wrote:
> Without the fork/exit/waitpid block of code, it prints the input
> successfully. With that code included, it goes into an infinite loop
> printing the first 78 lines of input, Every second pass over the input,the
> 78th line is garbled.
> 77 77 77 77 77xx
> 78 1 1xx
The 78th line looks like it's truncated after 16 characters.
> num_read: 30 at line 6433
> 2 2 2 2 2xx
>
> The input file "lines" is (all lines 52 charactures + \n == 53 characters):
53 * 77 = 4081
Add the 16 characters of the truncated line and you're right around
the magic number 4096, which is very likely the buffer size. So, even
if I can't explain every detail, this is another strong clue that stdio
buffering is involved somehow.
Reply to: