Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
605 views
in Technique[技术] by (71.8m points)

perl - Why doesn't my parent process see the child's output until it exits?

Consider the following script:

use IO::File;
$| = 1;
my ($handle, $pid) = myPipe();
if ($pid == 0) {
  print "$$";
  sleep 5;
  exit;
}

print "child: ".<$handle>."
";

sub myPipe {
  my $handle = new IO::File();
  my $pid = open($handle, "-|");
  return ($handle, $pid);
}

In this case, the "child:" message doesn't appear for 5 seconds after the process starts. If I remove the sleep call from the forked child, then it prints immediately. Why does the forked child have to exit for the pipe to flush to the parent?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

There are two issues. First, the child process is buffering its output; and second, the parent process is using the <> operator, which blocks until a complete line is available, or until end-of-file.

So, one way to get the result you were expecting is to have the child process close its output stream immediately after writing:

if ($pid == 0) {
    print "$$";
    close STDOUT;
    sleep 5;
    exit;
}

Another way is to add a newline to the child process's output, then flush the stream:

if ($pid == 0) {
    print "$$
";
    STDOUT->flush;  # "close STDOUT;" will work too, of course
    sleep 5;
    exit;
}

The flush is necessary because pipes are (typically) unbuffered, rather than line-buffered as streams connected to the terminal usually are.

A third alternative is to set the child process's output stream to autoflush:

if ($pid == 0) {
    $| = 1;
    print "$$
";
    sleep 5;
    exit;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...