IPC::Open3 and the error filehandle

P

Peter Makholm

I'm trying to use IPC::Open3 but have some problem with the error
filehandle not being used. Try the following script:

#!/usr/bin/perl

use IPC::Open3;
use Data::Dumper;

my ( $in, $out, $err );
open3($in,$out,$err, "/usr/bin/sort");

print Dumper [$in, $out, $err];

__END__


I would expect output like:

$VAR1 = [
\*Symbol::GEN0,
\*Symbol::GEN1,
\*Symbol::GEN2,
];

but I get output like

$VAR1 = [
\*Symbol::GEN0,
\*Symbol::GEN1,
undef
];


Reading the documentation, it clearly states that:

If CHLD_ERR is false, or the same file descriptor as CHLD_OUT, then
STDOUT and STDERR of the child are on the same filehandle. The
CHLD_IN will have autoflush turned on.

and $err is undef, which is clearly false. But what would be the
correct way to call open3?

The following works:

#!/usr/bin/perl

use IPC::Open3;
use Symbol;
use Data::Dumper;

my ( $in, $out, $err );
$err = gensym;
open3($in,$out,$err, "/usr/bin/sort");

print Dumper [$in, $out, $err];

__END__

but calling gensym by hand seems oldschool. But is there a better way?

//Makholm
 
C

comp.llang.perl.moderated

I'm trying to use IPC::Open3 but have some problem with the error
filehandle not being used. Try the following script:

#!/usr/bin/perl

use IPC::Open3;
use Data::Dumper;

my ( $in, $out, $err );
open3($in,$out,$err, "/usr/bin/sort");

print Dumper [$in, $out, $err];

__END__

I would expect output like:

$VAR1 = [
\*Symbol::GEN0,
\*Symbol::GEN1,
\*Symbol::GEN2,
];

but I get output like

$VAR1 = [
\*Symbol::GEN0,
\*Symbol::GEN1,
undef
];

Reading the documentation, it clearly states that:

If CHLD_ERR is false, or the same file descriptor as CHLD_OUT, then
STDOUT and STDERR of the child are on the same filehandle. The
CHLD_IN will have autoflush turned on.

and $err is undef, which is clearly false. But what would be the
correct way to call open3?

The following works:

#!/usr/bin/perl

use IPC::Open3;
use Symbol;
use Data::Dumper;

my ( $in, $out, $err );
$err = gensym;
open3($in,$out,$err, "/usr/bin/sort");

print Dumper [$in, $out, $err];

__END__

but calling gensym by hand seems oldschool. But is there a better way?


There was a thread about this not too long ago.
The open3 doc's aren't really informative IMO
since they don't clarify that you usually want to open a stderr
filehandle prior to the open3 call which just dup's to that opened fh.
(unless you pass "" which causes it to use stdout IIRC)

I usually do something like this:

open my $errfh ... or die...
open3( $in, $out, $errfh ) ...
 
B

Ben Morrow

Quoth Peter Makholm said:
I'm trying to use IPC::Open3 but have some problem with the error
filehandle not being used. Try the following script:

#!/usr/bin/perl

use IPC::Open3;
use Data::Dumper;

my ( $in, $out, $err );
open3($in,$out,$err, "/usr/bin/sort");
Reading the documentation, it clearly states that:

If CHLD_ERR is false, or the same file descriptor as CHLD_OUT, then
STDOUT and STDERR of the child are on the same filehandle. The
CHLD_IN will have autoflush turned on.

and $err is undef, which is clearly false. But what would be the
correct way to call open3?

The following works:

#!/usr/bin/perl

use IPC::Open3;
use Symbol;
use Data::Dumper;

my ( $in, $out, $err );
$err = gensym;
open3($in,$out,$err, "/usr/bin/sort");

print Dumper [$in, $out, $err];

__END__

but calling gensym by hand seems oldschool. But is there a better way?

No.

Ben
 
X

xhoster

Peter Makholm said:
but calling gensym by hand seems oldschool. But is there a better way?

There is, but the better way would break backwards compatibility, which is
probably why it hasn't been implemented.

The better way, IMHO, would be to make your own wrapper around open3
that only sends STDERR to STDOUT if ERRFH is false but defined. If ERRFH
is undefined, then it would be converted into a file handle with gensym,
just like the other two are. Maybe this behavior could be put into
IPC::Open3, but only turned on with a import flag. That way backwards
compatibility would be preserved.

Xho

--
-------------------- http://NewsReader.Com/ --------------------
The costs of publication of this article were defrayed in part by the
payment of page charges. This article must therefore be hereby marked
advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
this fact.
 
B

Ben Morrow

Quoth (e-mail address removed):
There is, but the better way would break backwards compatibility, which is
probably why it hasn't been implemented.

The better way, IMHO, would be to make your own wrapper around open3
that only sends STDERR to STDOUT if ERRFH is false but defined. If ERRFH
is undefined, then it would be converted into a file handle with gensym,
just like the other two are. Maybe this behavior could be put into
IPC::Open3, but only turned on with a import flag. That way backwards
compatibility would be preserved.

Better would be to replace ERRFH iff it is undef-but-an-lvalue.
Something like

sub open3 {
unless (defined $_[2]) {
local $@;
require Symbol;
eval { $_[2] = Symbol::gensym };
}

goto &IPC::Open3::eek:pen3;
}

This will keep the behaviour of an explicit

open3 $IN, $OUT, undef, ...;

which is more intuitive than having to use a false-but-defined value,
and matches the behaviour of open.

Ben
 
P

Peter Makholm

Ben Morrow said:
Better would be to replace ERRFH iff it is undef-but-an-lvalue.
Something like

Thanks to both of you. I'll add something along the lines of this to
our internal code library.

//Makholm
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,968
Messages
2,570,154
Members
46,702
Latest member
LukasConde

Latest Threads

Top