http://www.perlmonks.org?node_id=831175

7stud has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks,

According to perlfork:

Lifetime of the parent process and pseudo-processes

During the normal course of events, the parent process and every pseudo-process started by it will wait for their respective pseudo-children to complete before they exit.

However, when I call fork, and the parent does nothing and terminates, the child does not finish executing. For example, in the following program a child writes to a file every 2 seconds:

use strict; use warnings; use 5.010; my $child_pid = fork; $| = 1; if (!defined $child_pid) { say "**My error**: couldn't fork: $!"; } if ($child_pid) { #then in parent say "in parent..."; sleep 1; } else { #then in child open my $OUTFILE, '>', 'data1.txt' or die "**My error: couldn't open data1.txt: $!"; for (1 .. 10) { say $OUTFILE $_; sleep 2; } close $OUTFILE; }

...and the output is:

$ perl 1perl.pl in parent... $ cat data1.txt $

In other words, nothing gets written to the file--usually. About one in ten tries, this is the output:

$ perl 1perl.pl in parent... $ cat data1.txt 1 2 3 4 5 6 7 8 9 10 $

Can someone explain what is supposed to happen when the parent terminates before the child finishes executing?

Replies are listed 'Best First'.
Re: fork(): when parent exits, what happens to child?
by rubasov (Friar) on Mar 26, 2010 at 15:44 UTC
    You tried to avoid buffered output, but setting of $| affects the currently selected filehandle only (STDOUT by default). Try this after you opened data1.txt:
    my $saved_fh = select; select $OUTFILE; $| = 1; select $saved_fh;
    Hope that helps.

    update: to answer your original question: If the child separated itself from the parent (daemonized itself) then generally nothing happens (from the viewpoint of the child) when the parent dies. The orphaned child will get a new foster parent, this is called init in the Unix world. But for example if the child still shared its filehandles with the parent, and these filehandles are attached to a terminal and you close this terminal so these will get closed then the child will get a SIGPIPE. If the signal is not explicitly handled then the child will die. (But see "Complete Dissociation of Child from Parent" in perlipc for a more complete example.)

      init becomes a parent process
Re: fork(): when parent exits, what happens to child?
by jethro (Monsignor) on Mar 26, 2010 at 15:33 UTC
    You are suffering from buffering, if you wait long enough you will see all numbers in the file.

    Or put the open (with '>>' instead of '>') and close into the loop and you can see that the numbers drop in one by one

    It would have helped if you mentioned what OS you were talking about (ok, the word pseudo seem to suggest Windows)

Re: fork(): when parent exits, what happens to child?
by 7stud (Deacon) on Mar 26, 2010 at 15:59 UTC

    Hi,

    Thanks for the responses. The os is mac osx 10.4.11.

    It doesn't seem like a buffering problem to me. If the child actually finished executing, then wouldn't the close() execute on the output file handle, thus flushing the buffer to the file?

    Here is what happens when I turn on autoflush for the output filehandle:

    use strict; use warnings; use 5.010; my $child_pid = fork; $| = 1; if (!defined $child_pid) { say "**My error**: couldn't fork: $!"; } if ($child_pid) { #then in parent say "in parent..."; sleep 1; } else { #then in child open my $OUTFILE, '>', 'data1.txt' or die "**My error: couldn't open data1.txt: $!"; my $old = select $OUTFILE; $| = 1; select $old; for (1 .. 10) { say $OUTFILE $_; sleep 2; } close $OUTFILE; }
    --output:-- $ perl 1perl.pl in parent... $ cat data1.txt 1 2 $
      If the child actually finished executing, then wouldn't the close() execute on the output file handle, thus flushing the buffer to the file?
      Yes, but you would have to wait 20 seconds before the child has put out all 10 numbers because of the 'sleep 2' line. When I tried your script and executed the 'cat data1.txt' immmediately or 10 seconds after I got the shell prompt back I saw an empty file. But after 20 seconds the file suddenly had all 10 numbers in it. Because of buffering.

      Even if you turn off the buffering you should not expect more than one number every two seconds to arrive in data1.txt. Again because of 'sleep 2'. You could do a 'tail -f data1.txt' to see exactly what is happening in realtime

        Even if you turn off the buffering you should not expect more than one number every two seconds to arrive in data1.txt. Again because of 'sleep 2'.

        Of course! So then the rule is: when a parent terminates, the child keeps on executing.

      The os is mac osx 10.4.11.

      You were quoting documentation on the Windows emulation of forks.

        Ok, I missed this in perlfork:

        On some platforms such as Windows where the fork() system call is not available, Perl can be built to emulate fork() at the interpreter level...

        This document provides a general overview of the capabilities and limitations of the fork() emulation.

        I'm still looking for an answer to, "What happens to the child when the parent terminates on unix systems?"

        Based on some of my output, I would say: all children are killed. However, about 1 in ten times the child successfully writes all the data to the file. How is that possible if a child is killed when the parent terminates?