2

im learning about fork() but something is working wrong in my ubuntu. im running this code:

#include <stdio.h>
#include <unistd.h>

int main(int argc, char **argv)
{
printf("--beginning of program\n");

int counter = 0;
pid_t pid = fork();

if (pid == 0)
{
    // child process
    int i = 0;
    for (; i < 5; ++i)
    {
        printf("child process: counter=%d\n", ++counter);
    }
}
else if (pid > 0)
{
    // parent process
    int j = 0;
    for (; j < 5; ++j)
    {
        printf("parent process: counter=%d\n", ++counter);
    }
}
else
{
    // fork failed
    printf("fork() failed!\n");
    return 1;
}

printf("--end of program--\n");

return 0;
} 

i know the parent and the child should run their code in no specific order so the code should return something like this:

-beginning of program
parent process: counter=1
parent process: counter=2
parent process: counter=3
child process: counter=1
parent process: counter=4
child process: counter=2
parent process: counter=5
child process: counter=3
child process: counter=4
child process: counter=5
--end of program--

But every time i run the program, they run in what it seems to be the same order. here is a capture of what i get every single time i run this program:

user@user-VirtualBox:~/Documents/S-O$ ./sample
--beginning of program
parent process: counter=1
parent process: counter=2
parent process: counter=3
parent process: counter=4
parent process: counter=5
--end of program--
user@user-VirtualBox:~/Documents/S-O$
child process: counter=1
child process: counter=2
child process: counter=3
child process: counter=4
child process: counter=5
--end of program--

it seems like the parent finish first, and then the child starts. but i guess thats not true. please note that the second shell prompt is opened by the program itself. any ideas of what may be happening?

Edit:

if i put an sleep(1) it works just fine. i still think that with no delay it shouldn't always have the same execution order. even counting until 100, it giver the same thing

Community
  • 1
  • 1
angel208
  • 281
  • 1
  • 5
  • 15
  • 1
    What happens when you use larger numbers? Throw a sleep in there on each loop and see what happens. – ChiefTwoPencils Nov 09 '15 at 03:46
  • 1
    Have you tried counting > 5? – John3136 Nov 09 '15 at 03:46
  • when i use a larger number it does just the same thing. – angel208 Nov 09 '15 at 03:49
  • 2
    I suspect you are seeing serialization based on standard out's buffered nature and how quickly a modern computer can count to five. I took this code and unbuffered stdout and bumped the loop limit from 5 to 10K. It then started to exhibit some interleaving of IO from the child and parent processes. – Erik Nov 09 '15 at 04:00
  • @Erik At what sort of numbers did the interleaving become visible? – tripleee Nov 09 '15 at 04:11
  • 1
    @tripleee I had both the parent and child count up to 10000 and modified stdout from line buffering to unbuffered ```setvbuf(stdout,NULL,_IONBF,0);``` and the child started interleaving at around 200 ( on my mid 2014 MBP at 2.mumble GHz ). Interestingly, removing the ```setvbuf``` resulted in the parent and child serializing again. – Erik Nov 09 '15 at 04:16
  • Possible duplicate of [Can the order of execution of fork() be determined?](https://stackoverflow.com/q/6696959/608639), [In fork() which will run first, parent or child?](https://stackoverflow.com/q/21586292/608639), [Is there a good way to alter execution order of child processes created with fork()?](https://stackoverflow.com/q/46523164/608639), [Using fork(), how can I make child process run always first?](https://stackoverflow.com/q/30276244/608639), etc. – jww Oct 28 '19 at 21:42

1 Answers1

2

Yes parent and children run their code in an almost unpredictable order (remember that there is no randomness), but your scheduler probably choose, after forking, to schedule the parent first and then the child. As both have a very small code, the parent is able to run all of its code, and then the children. To experiment something else you must do something much much more longer after forking in both processes (You will be able to see different interleaving of outputs for example).

The prompt is not produced by your code, but is an effect of it. When the parent process dies, the shell that ran it get control back and prompt you for another command, while in the same time the children is working and pollutes your terminal. The child has become an orphan process. To prevent this, you must tell the parent to wait its child by calling...wait().

Jean-Baptiste Yunès
  • 34,548
  • 4
  • 48
  • 69