Why is the output of my branching program different when giving output?

I looked at simple fork code and decided to try it myself. I compiled and then ran it from inside Emacs and got a different output for this output obtained when I ran it in Bash.

#include <unistd.h> #include <stdio.h> int main() { if (fork() != 0) { printf("%d: X\n", getpid()); } if (fork() != 0) { printf("%d: Y\n", getpid()); } printf("%d: Z\n", getpid()); } 

I compiled it with gcc and then ran a.out from inside Emacs and also connected it to cat and grep . and got it.

2055: X
2055: Y
2055: Z
2055: X
2058: Z
2057: Y
2057: Z
2059: Z

It is not right. Performing it only with Bash, I get (what I expected)

2084: X
2084: Y
2084: Z
2085: Y
2085: Z
2087: Z
2086: Z

edit - skipped several lines of a new line

What's happening?

+8
c linux bash pipe fork
source share
4 answers

The order in which different processes write their conclusion is completely unpredictable. Therefore, the only surprise is that sometimes the seal statement “X” sometimes happens twice.

I believe this is because sometimes in the second fork() output line including "X" is in the output buffer that needs to be flushed. So both processes end up printing it. Since getpid() has already been called and converted to a string, they will show the same pid.

I was able to play a few lines of "X", but if I add fflush(stdout); just before the second fork() , I always see only one line of "X" and always only 7 lines.

+11
source share

I think I know what is going on. Buffering stdio will be different when the output is tty depending on when it is a pipe or file. Child processes inherit parent buffers. When they turn red, you can get a double exit.

If you add

 fflush(stdout); 

immediately after each call to printf() , you will see what I mean.

Interestingly, it differs when the standard output is a tty device. Perhaps the library knows what this means, and is reset after each line breaks or something like that.

+8
source share

So, I think you're wondering why you get more than one "X"?

This is because buffered output is purged twice.

When you pass the output of the program, the stdio library recognizes that your output is not a terminal, and it switches to block buffering instead of line buffering. Therefore, there is no output yet, when the fork process and so now both the parent and the child have pending output.

+6
source share

If you used stdout at all before forking, you should call fflush(stdout) before fork() (as well as for any other FILE output you use). Otherwise, the result is undefined . The effect you see comes from stdout buffered by line when it is connected to the terminal, but fully buffered when it is connected to the pipe. This is not required, but recommended by standards (POSIX).

+3
source share

Source: https://habr.com/ru/post/651311/


All Articles