Search code examples
perlioipcstdinchild-process

Why does the program shown in "7.2.39 IPC::Open2" of Programming Perl actually ends?


The program I am referring to is the second program shown in this section here. A small modification of it is:

#!/usr/bin/perl -w
use IPC::Open2;
use Symbol;

$WTR = gensym();  # get a reference to a typeglob
$RDR = gensym();  # and another one

$pid = open2($RDR, $WTR, 'bc');
print "$pid\n";

while (<STDIN>) {           # read commands from user
    print $WTR $_;          # write a command to bc(1)
    $line = <$RDR>;         # read the output of bc(1)
    print STDOUT "$line";   # send the output to the user
}

This program runs ok. Say its name is prop_7_2_39_2.pl, so a typical interaction with it is:

>./prop_7_2_39_2.pl
75955
2+2
4
quit

>

That is, after typing "quit", child process bc becomes defunct, and after that I need to feed a newline to actually finish the perl parent. Why the <STDIN> is evaluated to false? I understand that perl evaluates definition of <STDIN>. The somewhat related program

#!/usr/bin/perl -w
while(<STDIN>){}

does not end.


Solution

  • After sending quit to bc it terminates which closes the reading end of the pipe. Your next print $WTR $_ will then fail and generate the SIGPIPE signal that terminates the program - unless you install a signal handler for it.

    An alternative solution could be to check that reading from bc after you've sent something to it succeeds:

    while (<STDIN>) {              # read commands from user
        print $WTR $_;             # write a command to bc(1)
        my $line = <$RDR>;         # read the output of bc(1)
    
        if($line) {
            print STDOUT "$line";  # send the output to the user
        } else {
            last;                  # break out of the while loop
        }
    }
    print "Controlled ending...\n";