fork() Parent and child Processes of output - c

void main(){
if(fork()==0)
printf("a");
else{
printf("b");
waitpid(-1,NULL,0);
}
printf("c");
exit(0);
}
Question: what is the output of the program?
a. acbc
b. bcac
c. abcc
d. bacc
e. A or C or D (Correct Answer)
So I am trying to figure out why C is one of corret answer.The following is my reasoning:
The child process go first then stop and pass control to the parent process, ('a' print out)
then parent process executes ("b" print out) because of waitpid(),
parent pass
control back to child so in child process (c print out) and the child is reaped.
Finally, back to the parent process "c" print out. So we have abcc.
Am I right?

Theoretically, your answer is correct, it could happen like this (so at the end (a), (c), (d) seem they could happen).
Practically, the only correct answer is (a).
The reason for that is that stdio uses internally buffers for caching the output and avoiding expensive system calls. Therefore, until your program outputs `\n' (newline) or exits, there is no output at all.
So the real scenario is going to be:
child push character 'a' into buffer, then 'c' into buffer.
parent simultaneously pushes character 'b' into buffer and waits for the child.
child exits and flushes buffer containing "ac" before that.
parent returns from waitpid() and pushes 'c' into buffer.
parent exits and flushes buffer containing "bc".
About the second part:
SIGKILL can kill any process (apart from some system processes). Child process is regular process like any other.
waitpid is to wait for child process until it exits. It has nothing to do with killing processes, it only waits (either due its own exit or due to being killed, no matter by which signal).

Your reasoning about how C could happen is correct. Timing (going down) would look something like this:
Parent Child
a
b
(waitpid)
c
c

Related

How can output from parent and child of fork() system call interleave with each other?

code reads something like :
pid=fork()
if(pid){
print parent_id
print parent_id
}
else{
print child_id
print child_id
}
when it was executed it was 
child 
parent 
child 
parent
I don't understand how this could happen because child and parent should be printed consecutively.
You probably have a mutli-core CPU, so both parent and child can both be running on separate CPU cores. Printing is slow enough that the parent process has time to gets its 1st print started before your child process's 2nd print starts.
Or if not, on a single-core machine then scheduling could context-switch after one print.
The whole point of fork is to create a 2nd process that's also running; there should be no expectation that their system calls don't interleave with each other.
Existing near-duplicates about fork race conditions / timing, although those primarily about which runs first, not any expectation of continuing to run for multiple system calls before the other process can do anything.
fork(), runs always the parent first and then the child
Who executes first after fork(): parent or the child?
In fork() which will run first, parent or child?
Which process runs first when a fork() is called
And more generally Understanding parent and child process execution order about making multiple system calls including read in both parent and child, causing one or both to block.
And two where people had the opposite problem: they expected interleaving of output but didn't get it. (Perhaps because of buffered I/O resulting in only one write system call, if run from an IDE with output connected to a pipe instead of tty perhaps.)
fork() does not run parallel
Child process starts after parent process

How is the flow of control in this program involving fork() system call?

From what I read about fork() system call
Fork system call use for creates a new process, which is called child process, which runs concurrently with parent process
After a new child process created, both processes will execute the next instruction following the fork() system call
fork() returns 0 to the child process
fork() returns Process ID of newly created child process to parent process (Positive value)
fork() returns negative value if child process creation fails
In this piece of code
void foo() {
if (fork() == 0)
printf("Hello from Child!\n");
else
printf("Hello from Parent!\n");
}
int main() {
foo();
return 0;
}
The output is
Hello from Parent!
Hello from Child!
The child process was created when the control was inside the condition of if-else of function foo in main process.
So from where (which instruction) did the child process start executing?
As it can be observed from the output, Hello from Parent is printed when fork() returns 0. So from my understanding Hello from Parent was actually printed by the Child Process
fork() returned a positive value to the parent process and the parent process printed Hello from Child. Is my understanding about this correct?
And from which instruction exactly did the child process started executing? The function call to fork() was given inside the condition section of a if-else. So the child should have started executing after that if-else but that is not what is happening?
Let's start by identifying a primary misconception here:
As it can be observed from the output, Hello from Parent is printed when fork() returns 0. So from my understanding Hello from Parent was actually printed by the Child Process
The child and the parent are two separate processes running concurrently. The order of these two outputs isn't well-defined, will vary based on your kernel and other timing considerations, and isn't correlated with the fact that your code contains the if/else block written as you have it.1
Let's rewrite your code as a linear stream of "instructions" in an abstract sense:
0: Function foo():
1: Invoke system call fork(), no arguments, store result to $1
2: If $1 is non-zero, jump to label #1.
3: Invoke C function printf(), argument "Hello from Child!"
4: Jump to label #2.
5: Label #1:
6: Invoke C function printf(), argument "Hello from Parent!"
7: Label #2:
8: return control to calling function.
Once your program reaches 1:, the system call is invoked, transferring control to the kernel. The kernel duplicates the process, puts the PID of the child into the return value of fork in the parent process, and puts 0 into the return value of fork in the child. On x86, the return value is stored in register eax (rax for x64) as part of the syscall calling convention.
One of these two processes will eventually get scheduled to run by the kernel. In your case, the child process happened to be the first to get scheduled. Your user-mode code took control back from kernel mode, read the return value (out of eax/rax if on x86) which was zero, and did not jump to label #1. It printed Hello from Child!, and then returned from the function (to the caller of foo, since the child got a copy of the parent's stack).
The same happened for the parent, except the parent got a non-zero value back from the system call, and printed Hello from Parent!. It got scheduled to run, and your user-mode code took control from the kernel at the same point, just with a different value returned by the system call.
1 It's also possible that the two outputs might become interleaved in some way, but that's not as relevant to this discussion, and requires understanding how Linux processes perform I/O.
The child process is a second process that executes in parallel. You might just as easily have gotten
Hello from Child!
Hello from Parent!
For example, if you have a terminal window open, and you start firefox &, which runs “first,” the terminal window or the browser window? Both are running at the same time.
In fact, Linux starts the child process slightly before it resrarts the parent. This is because a large number of programs that call fork() immediately have the child exec() a program, which frees the parent from needing to share all its memory with the child. This is more efficient, because shared memory is copy-on-write.

Waiting process to return

Consider:
int main()
{
if (fork() == 0){
printf("a");
}
else{
printf("b");
waitpid(-1, NULL, 0);
}
printf("c");
exit(0);
}
(from Computer Systems, Bryant - O'Hallaron).
We are asked for all the possible output sequences.
I answered: acbc, abcc, bacc.
However, I am missing one output compared to the solution (bcac). I thought this output was not possible because the parent process waits for its child to return before printing c (waitpid). Is this not true? Why? And, in that case, what is the difference between the code above and the same without the waitpid line?
I don't see any way bcac is possible. At first I expected some trickery based on the stdio buffers being flushed in an unexpected order. But even then:
The child won't output c until after it has output a. Therefore the first c in bcac must have come from the parent.
The parent won't output c until after the waitpid completes. But that can't happen until after the child is finished, including the final stdio flush that happens during exit(). Therefore the first c is always from the child.
Proof by contradiction has been achieved... the output can't be bcac.
Well, there is one thing you could do to mess up the order. You could exec the program inside a process that already has a child which is about to exit. If the pre-existing child exits before the new child prints a, then the main process will detect that exit with waitpid, and go ahead and print its stuff and possibly exit before the child prints anything.
This is something to watch out for in setuid programs: don't assume that because your program only created one child process that it only has one child process. If you're in an advanced defensive-code learning context this answer makes sense. In a unix-newbie context it doesn't seem relevant, and it's probably better to just say bcac is impossible, even though it's technically not true.
It's tricky, but the call to waitpid can be interrupted (returns -1 and errno is EINTR). In this case the parent can output c before the child outputs anything and bcac is possible.
To prevent bcac from occurring, either a signal mask needs to be set, or, better, the waitpid return value is checked and if it was interrupted gets called again.

General Quick fork() explanation

suppose if we have something like this:
printf("A");
fork();
printf("B");
Is the output going to be
1) ABAB
2) ABB
Can you please explain?
The right answer is that it depends on the buffering mode of stdout, which the other answers seem to be ignoring.
When you fork with unflushed buffers and then continue using stdio in both processes (instead of the usual quick execve or _exit in the child process), the stuff that was in the buffer at the time of the fork can be printed twice, once by each process.
It is undefined and ABB, ABAB and AABB is possible. First (ABB) can happen on unbuffered output only; with buffered output both processes will have the A in their output buffer. By calling fflush(3) before the fork(2) you can enforce this behavior.
Order of last chars depends on order of execution; most likely you will get ABAB as in this short example the program won't be interrupted by the scheduler.
The output should read as "ABB"
fork copies the entire program into a new memory space and continues from the fork. Since both processes are running the same code, I would save the process id that is returned from fork, so the rest of your program knows what to do.
the output is simply abb. Fork create one new child process so after execution of fork() two process will run and generally child process first get the chance to executes. See before fork only one process so the out put before fork only once A. Then fork executes and hence two different process now running each will print B and hence output is ABB.

Does the C execv() function terminate the child proccess?

Heres a breakdown of my code.
I have a program that forks a child (and registers the child's pid in a file) and then does its own thing. The child becomes any program the programmer has dignified with argv. When the child is finished executing, it sends a signal (using SIGUSR1) back to the parent processes so the parent knows to remove the child from the file. The parent should stop a second, acknowledge the deleted entry by updating its table, and continue where it left off.
pid = fork();
switch(pid){
case -1:{
exit(1);
}
case 0 :{
(*table[numP-1]).pid = getpid(); //Global that stores pids
add(); //saves table into a text file
freeT(table); //Frees table
execv(argv[3], &argv[4]); //Executes new program with argv
printf("finished execution\n");
del(getpid()); //Erases pid from file
refreshReq(); //Sends SIGUSR1 to parent
return 0;
}
default:{
... //Does its own thing
}
}
The problem is that the after execv successfully starts and finishes (A printf statement before the return 0 lets me know), I do not see the rest of the commands in the switch statement being executed. I am wondering if the execv has like a ^C command in it which kills the child when it finishes and thus never finishes the rest of the commands. I looked into the man pages but did not find anything useful on the subject.
Thanks!
execv replaces the currently executing program with a different one. It doesn't restore the old program once that new program is done, hence it's documented "on success, execv does not return".
So, you should see your message "finished execution" if and only if execv fails.
execv replaces the current process with a new one. In order to spawn a new process, you can use e.g. system(), popen(), or a combination of fork() and exec()
Other people have already explained what execv and similar functions do, and why the next line of code is never executed. The logical next question is, so how should the parent detect that the child is done?
In the simple cases where the parent should do absolutely nothing while the child is running, just use system instead of fork and exec.
Or if the parent will do something else before the child exits, these are the key points:
When the child exits, the parent will get SIGCHLD. The default handler for SIGCHLD is ignore. If you want to catch that signal, install a handler before calling fork.
After a child has exited, the parent should call waitpid to clean up the child and find out what its exit status was.
The parent can also call wait or waitpid in a blocking mode to wait until a child exits.
The parent can also call waitpid in a non-blocking mode to find out whether the child has exited yet.
What did you expect to happen? This is what execv does. Please read the documentation which says:
The exec() family of functions replaces the current process image with a new process image.
Perhaps you were after system or something, to ask the environment to spawn a new process in addition to the current one. Or.. isn't that what you already achieved through fork? It's hard to see what you want to accomplish here.

Resources