is stuff before fork() executed? - Linux

This is a discussion on is stuff before fork() executed? - Linux ; Hi list, I have such a question, is the stuff before fork() function executed when it comes to the child process. I'm trying to catch the output of one program and I see the difference. $ cat print_before_fork.c #include int ...

+ Reply to Thread
Results 1 to 5 of 5

Thread: is stuff before fork() executed?

  1. is stuff before fork() executed?

    Hi list,

    I have such a question, is the stuff before fork() function executed
    when it comes to the child process.
    I'm trying to catch the output of one program and I see the
    difference.

    $ cat print_before_fork.c
    #include

    int main(int argc, char *argv[])
    {
    printf("before fork()\n");
    fork();
    printf("after fork()\n");

    return 0;
    }

    $ ./print_before_fork
    before fork()
    after fork()
    after fork()
    $ ./print_before_fork | tee output.txt
    before fork()
    after fork()
    before fork()
    after fork()

    As you can see, if i use a pipe trying to capture the output of the
    program, its output is different from the original one. So what's
    wrong? Any advice welcomed.

    --
    Guanqun

  2. Re: is stuff before fork() executed?

    On Nov 15, 10:48 am, "Guanqun...@gmail.com"
    wrote:
    > Hi list,
    >
    > I have such a question, is the stuff before fork() function executed
    > when it comes to the child process.
    > I'm trying to catch the output of one program and I see the
    > difference.
    >
    > $ cat print_before_fork.c
    > #include
    >
    > int main(int argc, char *argv[])
    > {
    > printf("before fork()\n");


    After I add one line: fflush(stdout);
    it's OK now.

    Sorry for the noise.

    > fork();
    > printf("after fork()\n");
    >
    > return 0;
    >
    > }
    >
    > $ ./print_before_fork
    > before fork()
    > after fork()
    > after fork()
    > $ ./print_before_fork | tee output.txt
    > before fork()
    > after fork()
    > before fork()
    > after fork()
    >
    > As you can see, if i use a pipe trying to capture the output of the
    > program, its output is different from the original one. So what's
    > wrong? Any advice welcomed.
    >
    > --
    > Guanqun



  3. Re: is stuff before fork() executed?

    "Guanqun.Lu@gmail.com" wrote:
    >Hi list,
    >
    >I have such a question, is the stuff before fork() function executed
    >when it comes to the child process.


    Heh heh... the answer isn't that the child buffer does
    execute, but rather that the parent *doesn't* execute!
    It gets interesting...

    >I'm trying to catch the output of one program and I see the
    >difference.
    >
    >$ cat print_before_fork.c
    >#include
    >
    >int main(int argc, char *argv[])
    >{
    > printf("before fork()\n");
    > fork();
    > printf("after fork()\n");
    >
    > return 0;
    >}
    >
    >$ ./print_before_fork
    >before fork()
    >after fork()
    >after fork()


    The default for stdout is "line" buffering when output
    is to a "terminal". With "line" buffering the newline
    in each of your printf statements causes the stdout
    buffer to be flushed immediately. Hence, the sequence
    of operations looks like this:

    1) printf() called
    A. text to stdout is buffered
    B. stdout buffer is flushed

    2) fork() is called

    4) first process calls printf
    A. text to stdout is buffered
    B. stdout buffer is flushed

    5) second process calls printf
    A. text to stdout is buffered
    B. stdout buffer is flushed

    The actual order for 4 and 5 is unknown, and could even
    be mixed between them too. Hence if you change the
    program to have the parent and child print different
    text it is impossible to determine which of the two will
    be first and which will be second. Indeed, it might
    change from one execution to the next.

    >$ ./print_before_fork | tee output.txt
    >before fork()
    >after fork()
    >before fork()
    >after fork()


    The output of your program is no longer going to a
    terminal, and the default buffering to a pipe is "block"
    buffering. It will not be flushed until either the
    buffer is filled, fflush() is called, or when the
    process closes stdout (for example when the process
    itself is about to exit).

    Hence the newline in the text no longer causes stdout to
    be flushed. The sequence of operations is different,
    and looks like this:

    1) printf() called, buffering text

    2) fork() is called (giving a stdout buffer to each process)

    4) first process calls printf, buffering more text

    5) second process calls printf, buffering more text

    6) first process, on exit, flushes stdout buffer

    7) second process, on exit, flushes stdout buffer

    >As you can see, if i use a pipe trying to capture the output of the
    >program, its output is different from the original one. So what's
    >wrong? Any advice welcomed.


    Here is one solution:

    #include
    #include
    #include

    int
    main(void)
    {
    printf("Parent before fork()\n");

    if (!isatty(STDOUT_FILENO)) {
    fflush(stdout);
    }

    switch (fork()) {
    case -1:
    perror("fork");
    exit(EXIT_FAILURE);
    case 0:
    printf("Child after fork()\n");
    break;
    default:
    printf("Parent after fork()\n");
    break;
    }
    return EXIT_SUCCESS;
    }

    Note that if you run that often enough there will be an
    instance where the order of the last two printf
    statements will be reversed.

    Another solution would be to unbuffer stdout before
    printf is called. See the man page for setbuf(3) for a
    lot more background information.

    See isatty(3) also.

    --
    Floyd L. Davidson
    Ukpeagvik (Barrow, Alaska) floyd@apaflo.com

  4. Re: is stuff before fork() executed?

    "Guanqun.Lu@gmail.com" writes:

    > Hi list,
    >
    > I have such a question, is the stuff before fork() function executed
    > when it comes to the child process.
    > I'm trying to catch the output of one program and I see the
    > difference.


    (snip)

    > As you can see, if i use a pipe trying to capture the output of the
    > program, its output is different from the original one. So what's
    > wrong? Any advice welcomed.


    It's in how the stdio library is buffering the output from printf().
    When your output is going to a terminal, the buffer is flushed at the
    end of each line; when it's going to something else, it doesn't get
    flushed until it fills (since it's not interactive, it doesn't need to
    flush as often). Note that when you're piping stdout to tee, from
    your program's point of view stdout is going to a pipe, not a
    terminal.

    Try this variant on your program and see what happens:

    #include

    int main(int argc, char *argv[])
    {
    printf("before fork()\n"); fflush(stdout);
    fork();
    printf("after fork()\n");

    return 0;
    }

    Also, man setbuf to see how to change the stream buffering for an
    entire program (instead of flushing by hand when desired, like I did
    above).

  5. Re: is stuff before fork() executed?

    On 11月15日, 下午1时24分, fl...@apaflo.com (Floyd L.Davidson) wrote:
    > "Guanqun...@gmail.com" wrote:
    > >Hi list,

    >

    [...]
    >
    > The output of your program is no longer going to a
    > terminal, and the default buffering to a pipe is "block"
    > buffering. It will not be flushed until either the
    > buffer is filled, fflush() is called, or when the
    > process closes stdout (for example when the process
    > itself is about to exit).


    Thanks for your input.
    I have a better understanding of the program.

    [...]
    >
    > #include
    > #include
    > #include
    >
    > int
    > main(void)
    > {
    > printf("Parent before fork()\n");
    >
    > if (!isatty(STDOUT_FILENO)) {
    > fflush(stdout);
    > }
    >
    > switch (fork()) {
    > case -1:
    > perror("fork");
    > exit(EXIT_FAILURE);
    > case 0:
    > printf("Child after fork()\n");
    > break;
    > default:
    > printf("Parent after fork()\n");
    > break;
    > }
    > return EXIT_SUCCESS;
    >
    > }
    >
    > Note that if you run that often enough there will be an
    > instance where the order of the last two printf
    > statements will be reversed.


    Yeah, it depends on which process is scheduled first.

    >
    > Another solution would be to unbuffer stdout before
    > printf is called. See the man page for setbuf(3) for a
    > lot more background information.
    >
    > See isatty(3) also.


    Thanks.

    >
    > --
    > Floyd L. Davidson
    > Ukpeagvik (Barrow, Alaska) fl...@apaflo.com



+ Reply to Thread