Search code examples
cfor-loopprintfbufferfork

How many times will each number be printed if the execvp() fails? I get C 3 times when running but my logic says C 2 times


the code:

int main(int argc, char *argv[]) {
    int i;
    for (i = 1; i < 3; i++) {
        if (fork() == 0) {
            printf("A");
            execvp("./prog2", &argv[1]);
            printf("B");
            exit(1);
        } 

        printf("C");
    }

    printf("D");
    return 0;
}

i expect something like this to happen(check photo), parent holds C into its buffer(first iteration) then holds CC after the second iteration and finally prints CCD, as for the children, first prints AB then exits same for the second one(second iteration). so i would say: A->two times, B->two times, C->two times and D->one time. But what i get when running it is:A->two times, B->two times, C->THREE times and D->one time. which is correct and why?(help would be much appreciated i have an exam soon)photo


Solution

  • i expect something like this to happen(check photo), parent holds C into its buffer(first iteration) then holds CC after the second iteration and finally prints CCD, as for the children, first prints AB then exits same for the second one(second iteration). so i would say: A->two times, B->two times, C->two times and D->one time. But what i get when running it is:A->two times, B->two times, C->THREE times and D->one time. which is correct and why?

    The standard output is buffered by default, and the buffer lives in the process's memory. Therefore, each time the parent process forks, the child receives a copy of the parent's stdout buffer, including any contents it holds at that time.

    At the first fork, the parent's buffer is empty, but at the second fork, it contains the "C" that the parent printed at the end of the first loop iteration. Both parent and (second) child will eventually print that "C", which accounts for the extra you observed over what you expected. You could avoid that by inserting a call to fflush(stdout) at the bottom of the loop.

    Assuming all fork(), printf(), and exit() calls succeed, and all execvp()s fail, we have the following evolution of the output buffer contents in the various processes:

      P1 P2 P3
    1, 2      
    3   AB
    4,5 C AB
    6 C AB C
    7 C AB CAB
    8 CC AB CAB
    9 CCD AB CAB
    1. P1 enters the loop as the only process, not yet having called printf.
    2. P1 then forks P2, and in that iteration of the loop,
    3. P2 printfs "A" and then "B", then exits.
    4. P1 printfs "C".
    5. P1 then cycles back to the top of the loop and forks again.
    6. P3, forked from P1, initially has "C" in its copy of the stdout buffer.
    7. P3 printfs an additional "A" and "B", then exits.
    8. P1 printf a "C", then its loop terminates.
    9. Finally, P1 printfs a "D".

    Each processes flushes its buffered output when it terminates. The outputs from the various processes will not be intermingled, but groupwise, they can appear in any order. For example,

    ABCABCCD
    

    Any way around, there should be a total of 2 As, 2 Bs, 3 Cs, and 1 D, exactly as you observe.