-1

The code looks something like this

int main() {
    printf("Starting process id is %d\t", getpid());
    if (fork() == 0) {
         fork();
     } else {
         fork();
         fork();
         exit(0);
     }
     printf("%d\t", getpid());
}

For the most part the outputs behave as expected where tracing. That is if we start with id n we get n+1 and n+5 being printed. However when I print the starting process id it gets printed 5 times and I am not sure why. Any help would be appreciated

Output from a sample run looks like this

Starting process id is 27252 pc@pc-VirtualBox:~/Desktop$ Starting porcess id is 27252 Starting porcess id is 27252 Starting porcess id is 27252 27253 Starting porcess id is 27252 Starting process id is 27252 27257

However I would have expected to see

Staring process id is 27252 27253 27257

Mitch
  • 3,342
  • 2
  • 21
  • 31

2 Answers2

2

It's because printf is buffering your output, not immediately flushing it to the device.

So, when you fork, the copy of the process also has that information buffered and each process will output the full string.

You should try calling fflush(stdout) (and possibly fsync(fileno(stdout)) depending on your platform) before each fork.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
1

Your initial printf doesn't end in a newline, and by default stdout connected to a terminal is line buffered. Thus, when you fork, the stdout buffer isn't empty, and when flushed by each child process on exit, it flushes the same data left in the buffer that it inherited.

To fix, do the following:

  1. fflush(stdout) before forking
  2. Exit the forked child processes with _exit, not exit (this can prevent buffers from being flushed, though it's implementation dependent so you can't make guarantees, but it also blocks atexit functions from being executed in the child process, which is usually the desired behavior)
  3. As an optional alternative or complement to #1, you can use tcflush to clear the buffered output prior to _exit-ing.
ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
  • So if I understand you correctly when I call printf() anything I try to print while my program is running is saved in a buffer and then when the program terminates the buffer is printed to stdout? – Mitch Oct 14 '17 at 01:01
  • @Mitchel0022: The usual rules are that `stderr` is unbuffered, `stdout` is line buffered when connected to a terminal (so it flushes the buffer when it sees a newline in output or the underlying buffer fills, whichever comes first), and `stdout` connected to anything else, and all other opened handles, are block buffered (so they flush when the buffer fills, the size of the buffer being implementation defined). The buffer is also flushed when the handle is closed (which happens implicitly on program exit), which is why all your children are printing. – ShadowRanger Oct 14 '17 at 01:05
  • Ahh, replacing the `\t` with a `\n` does force it to clear the buffer. Thank you for your explanation – Mitch Oct 14 '17 at 01:09