Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IPC::Open3 doesn't vivify an err filehandle #7515

Closed
p5pRT opened this issue Sep 27, 2004 · 5 comments
Closed

IPC::Open3 doesn't vivify an err filehandle #7515

p5pRT opened this issue Sep 27, 2004 · 5 comments

Comments

@p5pRT
Copy link

p5pRT commented Sep 27, 2004

Migrated from rt.perl.org#31738 (status was 'resolved')

Searchable as RT31738$

@p5pRT
Copy link
Author

p5pRT commented Sep 27, 2004

From perl-5.8.0@ton.iguana.be

Created by perl-5.8.0@ton.iguana.be

perl -le '
use IPC​::Open3;
my($wtr, $rdr, $err);
$pid = open3($wtr, $rdr, $err, "echo");
print "wtr=$wtr, rdr=$rdr, err=$err"
'

This outputs​:
wtr=GLOB(0x81622c0), rdr=GLOB(0x816208c), err=

So as you can see $err actually never gets filled in.
If you look in the code for IPC​::Open3, sub _open3 you see that
indeed $_[3] (which is where $err should get set) never gets
assigned a value.

Beyond that the logic also seems wrong for getting the err handle filled in​:

  $dad_err ||= $dad_rdr;

will duplicate $dad_rdr to $dad_err, which means that later the

  xpipe $dad_err, $kid_err if !$dup_err && $dad_err ne $dad_rdr;

will do nothing. So stderr will not get its own pipe. And indeed stracing
shows that only stdin and stdout get their own pipes.

Possibly this is intentional, because the docs say​:

  If either reader or writer is the null string, this will be replaced by
  an autogenerated filehandle. If so, you must pass a valid lvalue in
  the parameter slot so it can be overwritten in the caller, or an excep-
  tion will be raised.

which indeed doesn't talk about $err (and it talks about empty strings
and not undef really). But in that case the synopsis is completely
misleading because that says​:

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

which suggests $err is now something you can use instead of just a
useless placeholder (you could just as well directly pass undef, it
doesn't get assigned anyways). And in fact if you weren't interested
in catching STDERR, you could just as well have used open2 instead of
open3. So I think that a behaviour where $err gets its own pipe and
gets filled in makes more sense.

(Mmm, and why is the code playing ugly gensym games anyways now that
we have autovivified filehandles ? E.g. at first sight it looks like
the $kid gensym assigns can simply be dropped if the xpipe error
message is modified to not refer to its arguments)

Perl Info

Flags:
    category=core
    severity=low

This perlbug was built using Perl v5.8.5 - Sun Sep 26 00:52:21 CEST 2004
It is being executed now by  Perl v5.8.4 - Thu Jun  3 13:28:19 CEST 2004.

Site configuration information for perl v5.8.4:

Configured by ton at Thu Jun  3 13:28:19 CEST 2004.

Summary of my perl5 (revision 5 version 8 subversion 4) configuration:
  Platform:
    osname=linux, osvers=2.6.5, archname=i686-linux-64int-ld
    uname='linux quasar 2.6.5 #8 mon apr 5 05:41:20 cest 2004 i686 gnulinux '
    config_args=''
    hint=recommended, useposix=true, d_sigaction=define
    usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef
    useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
    use64bitint=define use64bitall=undef uselongdouble=define
    usemymalloc=y, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2 -fomit-frame-pointer',
    cppflags='-fno-strict-aliasing -I/usr/local/include'
    ccversion='', gccversion='3.4.0 20031231 (experimental)', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=12345678
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
    ivtype='long long', ivsize=8, nvtype='long double', nvsize=12, Off_t='off_t', lseeksize=8
    alignbytes=4, prototype=define
  Linker and Libraries:
    ld='cc', ldflags =' -L/usr/local/lib'
    libpth=/usr/local/lib /lib /usr/lib
    libs=-lnsl -ldb -ldl -lm -lcrypt -lutil -lc
    perllibs=-lnsl -ldl -lm -lcrypt -lutil -lc
    libc=/lib/libc-2.3.2.so, so=so, useshrplib=false, libperl=libperl.a
    gnulibc_version='2.3.2'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fpic', lddlflags='-shared -L/usr/local/lib'

Locally applied patches:
    


@INC for perl v5.8.4:
    /usr/lib/perl5/5.8.4/i686-linux-64int-ld
    /usr/lib/perl5/5.8.4
    /usr/lib/perl5/site_perl/5.8.4/i686-linux-64int-ld
    /usr/lib/perl5/site_perl/5.8.4
    /usr/lib/perl5/site_perl
    .


Environment for perl v5.8.4:
    HOME=/home/ton
    LANG (unset)
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/ton/bin.Linux:/home/ton/bin:/home/ton/bin.SampleSetup:/opt/schily/bin:/usr/local/bin:/usr/local/sbin:/home/oracle/product/9.0.1/bin:/usr/local/ar/bin:/usr/games/bin:/usr/X11R6/bin:/usr/share/bin:/usr/bin:/usr/sbin:/bin:/sbin:.
    PERL_BADLANG (unset)
    SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Dec 3, 2011

From @jkeenan

On Mon Sep 27 07​:05​:23 2004, perl-5.8.0@​ton.iguana.be wrote​:

perl -le '
use IPC​::Open3;
my($wtr, $rdr, $err);
$pid = open3($wtr, $rdr, $err, "echo");
print "wtr=$wtr, rdr=$rdr, err=$err"
'

This outputs​:
wtr=GLOB(0x81622c0), rdr=GLOB(0x816208c), err=

So as you can see $err actually never gets filled in.
If you look in the code for IPC​::Open3, sub _open3 you see that
indeed $_[3] (which is where $err should get set) never gets
assigned a value.

Beyond that the logic also seems wrong for getting the err handle
filled in​:

$dad\_err ||= $dad\_rdr;

will duplicate $dad_rdr to $dad_err, which means that later the

xpipe $dad\_err\, $kid\_err if \!$dup\_err && $dad\_err ne $dad\_rdr;

will do nothing. So stderr will not get its own pipe. And indeed
stracing
shows that only stdin and stdout get their own pipes.

Possibly this is intentional, because the docs say​:

   If either reader or writer is the null string\, this will be

replaced by
an autogenerated filehandle. If so, you must pass a valid
lvalue in
the parameter slot so it can be overwritten in the caller, or
an excep-
tion will be raised.

which indeed doesn't talk about $err (and it talks about empty strings
and not undef really). But in that case the synopsis is completely
misleading because that says​:

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

which suggests $err is now something you can use instead of just a
useless placeholder (you could just as well directly pass undef, it
doesn't get assigned anyways). And in fact if you weren't interested
in catching STDERR, you could just as well have used open2 instead of
open3. So I think that a behaviour where $err gets its own pipe and
gets filled in makes more sense.

(Mmm, and why is the code playing ugly gensym games anyways now that
we have autovivified filehandles ? E.g. at first sight it looks like
the $kid gensym assigns can simply be dropped if the xpipe error
message is modified to not refer to its arguments)

Confirmed that, seven years later, problem persists​:

$ perl -le '

use IPC​::Open3;
my($wtr, $rdr, $err);
$pid = open3($wtr, $rdr, $err, "echo");
print "wtr=$wtr, rdr=$rdr, err=$err"
'
wtr=GLOB(0x1804100), rdr=GLOB(0x1804110), err=

Thank you very much.
Jim Keenan

@p5pRT
Copy link
Author

p5pRT commented Dec 3, 2011

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Dec 3, 2011

From @ikegami

On Fri, Dec 2, 2011 at 7​:31 PM, James E Keenan via RT <
perlbug-followup@​perl.org> wrote​:

On Mon Sep 27 07​:05​:23 2004, perl-5.8.0@​ton.iguana.be wrote​:

perl -le '
use IPC​::Open3;
my($wtr, $rdr, $err);
$pid = open3($wtr, $rdr, $err, "echo");
print "wtr=$wtr, rdr=$rdr, err=$err"
'

This outputs​:
wtr=GLOB(0x81622c0), rdr=GLOB(0x816208c), err=

So as you can see $err actually never gets filled in.

I was going to suggest that the resolution should be a clarification of the
documentation for the following reasons​:

  - It's not practical to work around valid code C<< open3($wtr, $rdr,
  undef, 'echo') >>.
  - It's surely an error to use two identical handles, in which case
  leaving $err undef is safer.
  - In the spirit of "common tasks should be easy, rare and odd tasks
  possible", the ticket creator can always add C<< $err ||= $rdr; >> to their
  code to get the desired behaviour.

But the documentation is already quite clear about this​:

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 (this means that an
autovivified lexical cannot be used for the STDERR filehandle, see SYNOPSIS)

If this was a bug when the requester filed it, it's already been resolved
through a documentation change. Marking as resolved.

- Eric

@p5pRT
Copy link
Author

p5pRT commented Dec 3, 2011

@ikegami - Status changed from 'open' to 'resolved'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant