For Programmers: Free Programming Magazines  


Home > Archive > PERL Miscellaneous > October 2007 > IPC::Open3 and the error filehandle









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author IPC::Open3 and the error filehandle
Peter Makholm

2007-10-26, 7:07 pm

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
comp.llang.perl.moderated

2007-10-26, 7:07 pm

On Oct 26, 6:33 am, Peter Makholm <pe...@makholm.net> 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

Ben Morrow

2007-10-26, 7:07 pm


Quoth Peter Makholm <peter@makholm.net>:
> 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");
>

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

xhoster@gmail.com

2007-10-26, 7:07 pm

Peter Makholm <peter@makholm.net> 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.
Ben Morrow

2007-10-26, 7:07 pm


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

Peter Makholm

2007-10-29, 8:05 am

Ben Morrow <ben@morrow.me.uk> 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
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com