Unexpected behaviour of fork() - c

I m doing some C program using fork()
But I'm getting unexpected output.
#include <stdio.h>
main(){
printf("\nStart of Program");
fork();
printf("\nEnd of Program");
}
Output:
Start of Program
End of ProgramStart of Program
End of Program
Why do I get this output ?
Output should be this:
Start of Program
End of Program
End of Program

This issue is happening because of buffering.
Quoting this post.
When the output of your program is going to a terminal (screen), it is line buffered. When the output of your program goes to a pipe, it is fully buffered.
The posts also contains line by line explanation.

This is because of printf(), printf is buffering the output and only print when he reaches a '\n', so when reaching printf("\nEnd of Program"); printf() prints the content of the buffer which is "Start of Program".
Because fork() duplicates your stack, printf() buffer is duplicated too.
Try:
#include<stdio.h>
main(){
printf("Start of Program\n");
fork();
printf("End of Program\n");
}

Few things here need to check.
From where it is printing "student". I do not see any where you are printing student in your code.
The ideal output is
Start of Program
End of Program
End of Program
If you are not getting above output I will suspect, when fork executed and child got created probably your standard output print was not complete. Flush or \n as last char in print is a must to complete the print job,
To verify this what you can do is, before fork just use fflush.
Also in printf use \n as last char.
#include<stdio.h>
main()
{
printf("Start of Program\n");
fflush(NULL);
fork();
printf("End of Program\n");
}
Try this and let us know.

when fork is come then new process is created.
so end of program before fork call process and after fork call is printed. so that's logic.

I compiled that code myself, and I get following output:
Start of Program
End of Program
Start of Program
End of Program
Which is correct since fork() spawns exactly the same child process its forked from.
Edit: Thanks to the comments, I found out whats really going on. Fork behaves as expected, but the input buffer is not getting flushed before the child process is executed. I've modified the original code to this:
#include <stdio.h>
main(){
printf("\nStart of Program\n");
fflush(stdout);
fork();
printf("\nEnd of Program\n");
}
And the output now reads:
Start of Program
End of Program
End of Program
Which indicates that indeed, fork() only spawns the child process executing downwards from after the fork() call.

Related

Unexpected output on a fork call in C [duplicate]

This question already has answers here:
Why is main called twice?
(3 answers)
Closed 1 year ago.
I encountered this in my school work and it didn't produce what I thought it should:
int main() {
printf("c");
fork();
printf("d");
}
I know there are several things that aren't good about this code (i.e. no parameters in main, no variable for the return value from fork, no return statement at the end, etc.), but this is how it was presented and it's not relevant to my question anyway.
This code produces the output:
cdcd
It was my understanding that when fork is called, both parent and child would resume/begin on the line after the fork call. Based on that, I would have expected the output to be:
cdd
Assuming, of course, that the fork call is successful. Can anyone explain to me why that "c" is printed a second time even though it's on the line before the fork call?
Thanks!
M_MN
You forked your program before flushing stdout (i.e.: data was still in the output buffer). Just call fflush(stdout) to fix it:
❯ cat test.c
#include <stdio.h>
#include <unistd.h>
int main() {
printf("c");
fflush(stdout);
fork();
printf("d");
}
[22:14:01]~/devel
❯ clang test.c -o test
[22:14:07]~/devel
❯ ./test
cdd[22:14:09]~/devel
The reason you're seeing c twice is that the fork() duplicates the unprinted buffered output. You could flush the output stream before the fork():
fflush(stdout);
Or you could set stdout to be unbuffered, but you should do this first, before calling printf() the first time:
setvbuf(stdout, NULL, _IONBF, 0);
Here's what I'm guessing is happening. printf writes to the stream stdout. Since you didn't flush stdout after printing "c" nor did that string end in a new line, the character sat there in a user-space buffer. When you called fork, the child process got a copy of the parent's virtual address space including the buffered text. When both programs exited, their buffers were flushed and so "c" showed up twice.
Try adding fflush(stdout); just prior to the call to fork.

Understanding why fork gives different result in C

Although there are some similar questions like this and this
I still cannot understand why fork gives different output with the following two codes
#include<stdio.h>
void main()
{
printf("Hello World\n");
fork();
}
Gives output
Hello World
Where as this code
#include<stdio.h>
void main()
{
printf("Hello World");
fork();
}
Gives output
Hello WorldHello World
The second case is clear to me from the other questions, that both processes get a copy of the same buffer. So, after the fork, both processes eventually flush the buffer and print the contents to screen separately.
But I am not clear why the first case is so.
Let me explain it in simple words:
Consider,these two statements:
printf("Hello World")
and
printf("Hello World\n")
The STDOUT is line buffered that is printf will be executed only when the buffer is full or when it is terminated by a new line character
printf("Hello World") will not be guaranteed to display the output unless the
Buffer is full or terminated by new line character..Thus when a fork() is called,
Fork will create a copy of a process,this means that after fork, there are two identical processes,
each having a copy of the FILE* STDOUT Therefore, each process will have the same buffer contents of STDOUT
Since in your second program there is no newline character,
each process has the string in its buffer.
Then each process prints another string, and all of the contents are printed since it is terminated by a new line character. This is why you see two identical outputs.
But
In your first program,there is a new line character and it displays output
immediately after the statement is executed and hence it flushes the contents of buffer..thus when a fork() is called
The process tries to access the buffer but since the buffer is empty,it does not print anything
Thus,the different response is due to Buffering behavior of stdout
Hope it helps!!
It's due to the buffering behavior.
#include<stdio.h>
void main()
{
printf("Hello World\n");
fork();
}
flushes the output before you call fork, so the printing is already finished when it was still only a single process.
As to why printf("Hello World\n"); gets flushed immediately and printf("Hello World"); doesn't isn't that easy. It depends on the situation. In your case you probably ran it in the commandline where line buffering is common, line buffering means that it will be flushed once you got a newline. If you write to files it might buffer more before you get any output and you might see 2 outputs in the first case too.
If you want consistent behavior with flushing you might want to do it yourself.

Forking a process- execution before the system call (execution point)

"When we call fork() on a process and its child is created, it is said that the point of execution starts from the point next to the fork() call in both the processes. But when I checked,
main() {
printf("hello");
val =fork();
if(val==0){
printf("child");
}
if(val>0){
printf("parent");
}
}
This program printed hello also twice. I am a little confused. Please help me out.
When you do printf("hello");, the output is line buffered for STDOUT which is not flushed. Now when the buffer still containing data, fork() call makes both parent and child process inherit data present in the buffer making it print twice.
Ideally you should be flushing the standard output as below:
printf("hello");
fflush(stdout);
fork();

Questions on fork() [duplicate]

This question already has answers here:
printf anomaly after "fork()"
(3 answers)
Closed 8 years ago.
I am trying to understand fork(), and so I put together the following example:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
void main()
{
if(fork()==0)
{
printf("2");
if(fork()==0)
{
printf("4");
}
else
{
printf("3");
}
}
else
{
printf("1");
}
}
When I was tracing this on paper, I drew the following sketch:
So I believe the output should be 1234. However, when I run this code, the output is 12324. Why is that? Where is my mistake?
Update:
After reading the comments, it was suggested to do any of the following
Add \n to each printf statement
OR: Add fflush(stdout); after each printf statement
OR: Add setbuf(stdout, NULL); <---- this is what I ended-up doing :)
After updating my code, the output was indeed 1234.
printf() output is usually line-buffered. So when you fork(), the new processes gets the copy of the buffer as well. When the process exits, the whole buffer is flushed (or anytime it's flushed in the code or whenever the buffer becomes full). Hence, you see a copy of printf's output one more time.
1) You can flush it after each printf() call by using fflush(stdout);
2) or using \n for example:
printf("2\n");
Another way is to disable the buffering with:
setbuf(stdout, NULL);
Your analysis is almost correct. However, printf does not necessarily write immediately do file descriptor - output is buffered inside the process. The second process does fork after putting 2 in the buffer. Both second and third processes will have it in the buffer and print 2.
If you do printf("2\n") instead new line character will force printf to flush the buffer and you will see only one 2.

fork() and write commands

#include<stdio.h>
int main()
{
if (fork())
{
wait();
printf("Now I am showing you ls -l"); // why can't we see this ?
execlp("ls","ls", "-l", 0); //gets printed second
}
else
{
printf("We are in the child process."); // gets printed first
}
}
I have this simple peace of code. My question is why don't we see on the console the first print, in the parent process?
The printf function provides buffered IO. When printing to stdout, as you are here, the buffer will normally get flushed when you print a newline \n, which you have not done, so your string is sitting in a buffer waiting to be printed.
The next thing you are doing is calling execlp. The exec family of functions replace the current process with the new one you have specified. The buffer is lost without ever being flushed, because the whole process is replaced.
If you add \n to the strings you are printing, you will probably see the output.
you have to flush stdout before the execlp.
if you put a \n at the end of the printf (or you call fflush(stdout)) you will get the correct result
In the interactive case, standard output is line buffered by default. And that execlp() will replace its memory image, therefore that output line may be dropped before it is written to console.
Change that print() statement to
printf("Now I am showing you ls -l\n");
to fix this problem.
There is 2 problems with your code:
first you need to flush your outputs, either by adding \n in the strings or by calling fflush(stdout)
But it should be the job of the son to exec(), of course you can always exec in the parent, but this is probably not what you want.
A more common fork/exec sample looks like :
int main() {
if (fork()) { // parent
wait(NULL); // wait his child
printf("Ok, my children finished the job\n");
exit(0);
}
else { // child
printf("We are in the child process.\n"); // gets printed first
printf("Now I am showing you ls -l\n");
execlp("ls","ls", "-l", 0); // never return from this
}
}

Resources