So in the ubuntu terminal, when I run a simple piece of code using fork to print from the child as well as parent process, the terminal prints the child process' print statement on command line rather than before it. I want to know if there is a way around it.
I am a bit new to using syscalls so I really didn't try many things
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char* argv[]){
printf("(%d) Start\n", (int)getpid());
int rc = fork();
if(rc < 0 ){
fprintf(stderr, "Error\n");
exit(1);
}
else if(rc == 0){
printf("(%d) Hello from the child, I got %d. My parent is %d\n", (int)getpid(), (int)rc, (int)getppid());
}
else{
printf("(%d) Hello from the parent, I got %d. My parent is %d\n", (int)getpid(), (int)rc, (int)getppid());
}
return 0;
}
I expected the the printed statements to all be in between two command lines, but the last line kept being printed on the command line:
This is a classic example of a race condition. After the fork
call you have, by definition, two separate processes and two threads of control. They are running, notionally, in parallel. (On a multiprocessor or multicore machine, they may be actually running in parallel.)
In the parent, we have these things happening:
In the child, we have these things happening
It's the parent process (in this context) that is a child of the invoking shell. So it's the parent process that's being waited for by the shell; it's the exit from the parent process (step 2) that will trigger the printing of the next shell prompt (step 3). It's more complicated to say what happens after the child exits, but since it doesn't result in anything being printed (or anything at all, that we can see), it doesn't end up mattering.
But since we have two threads of control, and a race condition, we can see different outcomes depending on how the various printing steps are interleaved:
thread of control #1 thread of control #2
------ -- ------- -- ------ -- ------- --
1. Hello from the parent
4. Hello from the child
3. next shell prompt
or
1. Hello from the parent
3. next shell prompt
4. Hello from the child
or maybe
4. Hello from the child
1. Hello from the parent
3. next shell prompt
But which of these outcomes you get can depend on literally anything. (That's the nature of a race condition.) So I'm not too surprised that your professor's computer showed a different behavior. (For one thing, although MacOS is indeed very much Unix-like, it's based on a Mach microkernel underneath, which changes some things.)
If you're still unsatisfied, here is a -- possibly far-fetched -- analogy.
It sounds like you imagine that you shouldn't get another shell prompt back until the program -- the whole program -- has finished. It sounds like you believe it should be impossible for "the program" to print anything after it has finished, that is, after you have seen the next shell prompt which indicates that it has finished.
Suppose you run a therapy center. Suppose you have a "screaming room" where people can scream as loud as they want, to let out their frustrations. So when you hear screaming from that room, you know it's from one of your patients, but if there are no patients in there, you don't expect to hear any screaming.
So one day a woman comes in who's very stressed, and you usher her into the screaming room, and you hear quite a bit of screaming, but then after a while she comes back out, and you move the little sign on the door from "occupied" back to "unoccupied". But then, to your surprise, you hear another scream (more of a cry) coming from behind the door...
Oh, and did I mention that the reason the woman was so stressed to begin with was that she was heavily pregnant, about to give birth?