[sf-perl] IPC::Open3

Steve Fink sphink at gmail.com
Fri Sep 7 13:24:45 PDT 2007

On 9/7/07, David Alban <extasia at extasia.org> wrote:
> Greetings,
> I'm taking open3 for a test drive.  I thought that stderr would go to
> the err handle.  But it seems it doesn't.
>      1  #!/usr/bin/perl
>      2
>      3  use strict;
>      4  use warnings;
>      5
>      6  use IPC::Open3;
>      7
>      8  my $pid = open3( my $wfh, my $rfh, my $efh, qw( ls -ld foo bar ) );
>      9
>     10  while ( <$rfh> ) {
>     11    print "rfh: $_";
>     12  } # while
>     13
>     14  while ( <$efh> ) {
>     15    print "efh: $_";
>     16  } # while
> foo exists.  bar doesn't.  I'd expect the read file handle to contain
> stdout, i.e., the listing for foo.  I'd expect the error file handle
> to contain stderr, i.e., the message that bar doesn't exist.  But I
> get both in the read handle:
>     Use of uninitialized value in <HANDLE> at junk.perl line 14.
>     readline() on unopened filehandle at junk.perl line 14.
>     rfh: ls: cannot access bar: No such file or directory
>     rfh: -rw-r--r-- 1 dalban Users 0 Sep  7 11:11 foo
> What am I missing?

You were foolish enough to believe the documentation rather than the
documentation. Oh, and that the API would make some sort of sense.
What were you thinking?

perldoc IPC::Run3 gives as an example:

   my($wtr, $rdr, $err);
   $pid = open3($wtr, $rdr, $err, 'some cmd and args', 'optarg', ...);

which doesn't work. Well, it works according to the documentation:

       If ERRFH is false, or the same file descriptor as RDRFH, then STDOUT and
       STDERR of the child are on the same filehandle.

That's what is happening in your example. Your 'my $err' evaluates to
false, so STDOUT and STDERR both go to $rdr (which is automatically
created, as expected).

The example strongly implies that it should work as [both of us]
expected, but it doesn't. Instead, it gives you the useless behavior
observed. I'm guessing something got added on later as an
afterthought; probably the filehandle autovivification? It's a
relatively new feature in the core open().

I don't see any way to fix it, either. I thought that it should be
able to distinguish based on whether that 3rd parameter is lvaluable,
but it seems like anything undefined is lvaluable. Or something.

You can manually make it work:

  use Symbol;
  open3(my $wfh, my $rfh, (my $efh = Symbol::gensym), qw(...));

Isn't that beautiful?

More information about the SanFrancisco-pm mailing list