IPC::Open3 and the error filehandle

IPC::Open3 and the error filehandle

am 26.10.2007 15:33:07 von 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

Re: IPC::Open3 and the error filehandle

am 26.10.2007 21:35:20 von Charles DeRykus

On Oct 26, 6:33 am, Peter Makholm wrote:
> 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 ) ...


--
Charles DeRykus

Re: IPC::Open3 and the error filehandle

am 26.10.2007 22:22:20 von Ben Morrow

Quoth 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");
>

>
> 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

Re: IPC::Open3 and the error filehandle

am 26.10.2007 22:47:11 von xhoster

Peter Makholm wrote:
>
> 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.

Re: IPC::Open3 and the error filehandle

am 27.10.2007 00:57:20 von Ben Morrow

Quoth xhoster@gmail.com:
> Peter Makholm wrote:
> >
> > 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.

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::open3;
}

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

Re: IPC::Open3 and the error filehandle

am 29.10.2007 11:48:40 von Peter Makholm

Ben Morrow writes:

> 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