1

I'm just learning how to use fork() in C and i have troubles understanding execution flow.

the code:

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

int main() {
    printf("starting...\n");

    int x = 100;

    int rc = fork();

    if (rc < 0) {
        printf("unable to fork\n");
        exit(-1);
    } else if (rc == 0) {
        x = x + 200;
        printf("child x == %d\n", x);
    } else {
        x = x + 500;
        printf("parent x == %d\n", x);
    }
    return 0;
}

executes as you would think it will:

user@fedora> ./main
starting...
parent x == 600
child x == 300

the strange thing happens when i remove \n from printf("starting...\n");:

user@fedora> ./main
starting...parent x == 600
starting...child x == 300

Why when i remove \n the "starting..." prints twice when it clearly shouldnt?

Please could you explain why in this case printf("starting...") is executed twice?

Thank you!

U. Windl
  • 3,480
  • 26
  • 54
User
  • 19
  • 3
  • 3
    I'd assume that `printf` uses an internal line buffer that gets duplicated when you `fork()` the process. I could be wrong but I think that's what happening. – Marco Apr 29 '23 at 14:20
  • Because normally printf only flushes the output once `\n` is encountered. – Marco Apr 29 '23 at 14:21
  • "when it clearly shouldn't" No, it clearly might print twice, or it might only print once. But I suppose that usage of "clearly" depends on the reader understanding how buffering works. `printf` does *not* necessarily write any data to the output stream. It stores it in a buffer and writes it later. If "later" is after the fork, then you expect both the parent and the child to write it, so you see it twice. – William Pursell Apr 29 '23 at 14:24
  • You should also include the `\n` and try redirecting the output to a file. The behavior may surprise you, and you should understand it. – William Pursell Apr 29 '23 at 14:26

1 Answers1

5

Your problem isn't with the fork system call; rather, it's with the way C's common I/O operations are buffered.

In C, the printf() function doesn't always output to the terminal. Instead, it writes into a buffer, and when the buffer is flushed, the terminal is actually written to. This typically occurs when a newline '\n' is printed, the buffer is full, or the buffer is manually flushed with fflush(stdout).

The "starting..." string is written to the buffer in your code when the n is removed from the initial printf() statement, but it is not immediately flushed to the terminal.

The entire process, including the unflushed buffer, is then replicated when the fork() function is made. This indicates that "starting..." is now present in the output buffers of both the parent and the child processes.

Any unflushed output from terminated processes is automatically flushed. For each procedure, "starting..." is printed twice for this reason.

Keeping the n in the initial printf() instruction or manually flushing the buffer before invoking fork() are two ways to resolve this problem:

printf("starting...");
fflush(stdout);
Kristianko
  • 51
  • 4