5

I've just learnt about fork, and as I understand it the child process starts execution from the call to fork (otherwise fork would be recursive?).

However in this code (ideone link):

int main() {
  printf("%d: Common code1\n", getpid());
  if (fork() != 0) {
    printf("%d: Parent code\n", getpid());
  } else {
    printf("%d: Child code\n", getpid());
  }
  printf("%d: Common code\n", getpid());
}

The output is:

27380: Common code1
27380: Parent code
27380: Common code
27380: Common code1
27383: Child code
27383: Common code

I don't understand why the 4th line is printed? I could understand if it was printed from the child process and fork called main but it's printed from the parent, and fork doesn't call main.

Jonathan.
  • 53,997
  • 54
  • 186
  • 290
  • possible duplicate of [Why the output is printing twice?](http://stackoverflow.com/questions/3822755/why-the-output-is-printing-twice) – leppie Jan 26 '15 at 10:02
  • 4
    Did you really *have* to pick two extremely long strings that *only differ in one tiny character*? Do you hate us so much? – Kerrek SB Jan 26 '15 at 10:05
  • Extremely long? I just copied and pasted it and adding a 1 was the quickest war of differentiating – Jonathan. Jan 26 '15 at 10:07
  • I tried your code as is, and `Common code1` is only printed once. Are you sure your executable is up to date ? – Jukurrpa Jan 26 '15 at 10:08
  • 1
    This is almost certainly a duplicate, but not of that question. There, the fork is called before any printfs, and buffering is not an issue – William Pursell Jan 26 '15 at 10:09
  • @Jukurrpa, I'm running it on ideone (link in the question) and that's the output I get. – Jonathan. Jan 26 '15 at 10:09
  • It's not a duplicate of marked question. I'm asking about why code **before** the fork is printed twice. – Jonathan. Jan 26 '15 at 10:10
  • 1
    If you run the code in a terminal, the output may differ from running it in an environment like Ideone, since Ideone and similar services use file redirection. – millinon Jan 26 '15 at 10:12
  • Possible duplicate of [printf anomaly after "fork()"](https://stackoverflow.com/questions/2530663/printf-anomaly-after-fork) – Brian McCutchon May 19 '18 at 05:35

3 Answers3

9

Good question! I was a little bit confused at first.

When you use printf, the output is buffered. That means that things printed by printf won't be actually flushed to the console until a newline is reached, or even until the program terminates if stdout is redirected.

In this case. the parent PID's stdout buffer is being copied to the child during the fork. Then, both the parent and child write to their buffers before terminating. This results in duplicated data being printed.

Here's an ideone link that includes fflush(stdout); before fork() is called.

millinon
  • 1,528
  • 1
  • 20
  • 31
  • stdout is not a 'console unit'. Do not conflate the tty with stdout, as they are different things. – William Pursell Jan 26 '15 at 10:12
  • I wasn't attempting to explain the magic behind stdout; I attempted to explain the observed effect as relevant to the question, and to offer a solution. Thanks for the clarification! – millinon Jan 26 '15 at 10:19
3

The problem comes from buffering. When stdout is not associated with a terminal, it isn't line buffered. The strings you write are short enough to stay inside the buffer and are only written out once the program terminates. Thus, you first see process 27380 dumping its buffers and then process 27383 dumping its buffers. The line 27380: Common code1 hasn't been flushed out before the fork, so it's in the buffer of both the original and the forked process. Call fflush() right before forking to fix this problem.

fuz
  • 88,405
  • 25
  • 200
  • 352
2

Buffering. Printf does not (usually) write anything to stdout. It merely updates some internal data structures. Those data structures are duplicated in the child, and when the stream is flushed the data is written. You should flush(stdout) before you fork.

William Pursell
  • 204,365
  • 48
  • 270
  • 300