I'm learning about forking processes and memory management and I have come across this piece of code:
#include <stdio.h>
#include <libc.h>
int main() {
for (int i = 0; i < 3; ++i) {
printf("*");
fflush(stdout);
fork();
}
return 0;
}
By my calculations it should produce 7 stars: initial process prints a star (1 star), forks, now we have 2 processes, each of them prints a star (1 + 2 = 3), then they fork, so we have 4 processes, each of them prints a star and then dies as the program ends.
Thus, we should get 1 + 2 + 4 = 7 stars.
However, during some runs I get only 6 stars, like in the screenshot below:
Other times when I run the program everything is good and I get 7 stars as expected.
So far I have searched in the Internet and haven't found anything like that. Debugging also didn't help.
So, what can cause this strange behavior and how can I fix it?
When running this code from a terminal you will notice that your missing *
on some runs is not missing at all but printed after your program is finished.
For better understanding you might print the PID's instead of stars and an additional line when the process is about to finish:
int main() {
for (int i = 0; i < 3; ++i) {
printf("pid %d\n", getpid());
fflush(stdout);
fork();
}
printf ("pid %d terminates\n", getpid());
return 0;
}
The output on a run with missing print(s) will look something like this, indicating the terminal already returned before all processes have finished:
pid 31241
pid 31241
pid 31241
pid 31242
pid 31241 terminates
pid 31243
pid 31244 terminates
pid 31242
pid 31245
pid 31242 terminates
pid 31246 terminates
pid 31247 terminates
pid 31245 terminates
user@machine:~/bla$ pid 31243 terminates
pid 31248 terminates
To fix this you can let the parent process wait for its child processes before returning - this will cause your initial process to finish last and prevent the terminal from returning when there are still child processes running in the background:
while (wait(NULL) > 0);
printf ("pid %d terminates\n", getpid());