Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Statement before fork() printing twice [duplicate]

I was experimenting with fork() and re-direction to check whether the re-directions done in the parent apply to the child too. I wrote the following simple program

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

int main ()
{
    freopen( "error.txt", "w+t", stdout ); // From now on, stdout = error.txt
    printf (" ERROR!  WHY DONT U UNDERSTAND?\n");
    if ( fork() == 0 ) 
    {   
        printf(" I AM CHILD\n");
        exit(0);
    }   
    else-
    {   
        printf (" EITHER I AM A PARENT OR SOMETHING GOT SCREWED\n");
    }   


    return 0;
}

The output ( error.txt ) I got is

ERROR!  WHY DONT U UNDERSTAND?
EITHER I AM A PARENT OR SOMETHING GOT SCREWED
ERROR!  WHY DONT U UNDERSTAND?
I AM CHILD

Surprisingly, ERROR! WHY DONT U UNDERSTAND? is printing twice even though it appears much before the fork() is called and should only be printed once by the parent.

Can anyone shed some light on this?

like image 753
Pavan Manjunath Avatar asked May 22 '12 10:05

Pavan Manjunath


People also ask

Why is my output printing twice?

Because both the parent and child process are outputting their results.

Why fork twice?

Normally Nagios will fork() twice when it executes host and service checks. This is done to (1) ensure a high level of resistance against plugins that go awry and segfault and (2) make the OS deal with cleaning up the grandchild process once it exits.

How many times will a be printed fork ()?

fork() && fork() || fork(); printf will go a total of 5 times.

Does fork flush stdout?

Both sides of the fork inherit the unflushed buffer, so when each side of the fork hits the return statement and ends, it gets flushed twice. Before you fork, you should fflush(stdout); which will flush the buffer so that the child doesn't inherit it.


2 Answers

Since after reopen the stream is non-interactive, it's fully buffered and doesn't flush on '\n'. Before fork is called the buffer still contains the message, and after fork this buffered message was duplicated (because both processes got their own copies of stdout) and then flushed by both the parent and the child. See part 7.19.3 of C standard.

You can avoid such behavior by calling fflush just before fork.

like image 169
Alex Bakulin Avatar answered Oct 18 '22 22:10

Alex Bakulin


It's because of buffering. Do a fflush right after printf.

Both processes end up with the same copy of stdio's internal stuff and both proceed to flush it at exit. You might also prevent it from happening if you call _exit in the child.

like image 36
cnicutar Avatar answered Oct 18 '22 20:10

cnicutar