I try to learn the function fork(). However, the results performed using Code Runner in VScode are different from the results performed in a shell. Just like blew pictures show, I used same commands but get different results. I know that the second output in shell is right and I would like to know why is the first output printed by using Code Runner? Is something wrong about the plugin?
The code is like this.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
printf("Hello World\n");
fork();
fork();
fork();
exit(0);
}
It's a buffering issue.
When stdout
is connected to an actual terminal it will be line buffered That means the output is actually written to the terminal when the buffer is full, is explicitly flushed, or when you print a newline ('\n'
).
This is what happens in the second case.
In the first case, VSCode will not run it directly in a terminal, instead stdout
will be connected to a pipe which VSCode will then output in its "terminal". When connected to a pipe (or anything else that isn't a direct terminal) then stdout
will be fully buffered, where the output is flushed only when the buffer is full or explicitly flushed.
In this first case the buffer for stdout
will be inherited by the child processes, so each child-process you fork
will have its own copy of the existing buffer. And when each of the child-processes exits, their buffer will be flushed and actually written. Since there are a total of eight processes running, you will get the output eight times.
From your program to the actual output there might be multiple buffers. But the buffer I'm talking about above is the high-level stdout
buffer only.
When output to stdout
is to an actual command-line environment then output will be written on newline. Otherwise the output will be buffered until the buffer is full (or explicitly flushed with fflush(stdout)
).
When running in an IDE of some kind, the output pane or window is usually a GUI control of the IDE itself, it's not a command-line environment. Therefore all output written on stdout
will be stored in the stdout
buffer until it's full, and then the IDE will receive it so it can write it to the output pane or window.
Since the stdout
buffer is not flushed, when you do fork()
the new child process, being an almost exact copy of the parent process, will start with a stdout
buffer that already have data in it.
When the child process exits then the stdout
buffer will be flushed and output written to the layers below, and the IDE will receive it to print. Since you have multiple child (and grandchild) processes, in addition to the original parent process, you will get output from each of the processes.