3

I am reading the perlcritic documentation to avoid backticks and use IPC::Open3 here:

http://perl-critic.stacka.to/pod/Perl/Critic/Policy/InputOutput/ProhibitBacktickOperators.html

I am trying to find the least verbose option that will work and satisfy perlcritic:

#!/usr/bin/perl
use strict;
use warnings;
use IPC::Open3 'open3'; $SIG{CHLD} = 'IGNORE';
my $cmd = 'ls';
my ($w,$r,$e); open3($w,$r,$e,$cmd);
my @o = <$r>; my @e = <$e>;
1;

But it complains with the following error:

Use of uninitialized value in <HANDLE> at ipc_open3.pl line 7

Any ideas?

EDITED: Ok, here is what I've got. Unless there is a way to simplify it, I'll stick to this:

#!/usr/bin/perl
use strict;
use warnings;
use IPC::Open3 'open3'; $SIG{CHLD} = 'IGNORE';
use Symbol 'gensym';
my $cmd = 'ls';
my ($w,$r,$e) = (undef,undef,gensym); my $p = open3($w,$r,$e,$cmd);
my @o = <$r>; my @e = <$e>;
1;
719016
  • 9,922
  • 20
  • 85
  • 158

2 Answers2

8

The advice on that page is awful. IPC::Open3 is a low-level module that's hard to use. The very code the page suggests will hang (deadlock) if lots is sent to STDERR.

Use IPC::Run3 or IPC::Run instead.

Examples:

run3 $cmd, undef, \my $out, \my $err;
run3 [ $prog, @args ], undef, \my $out, \my $err;
run3 [ $prog, @args ], undef, \my @out, \my @err;
ikegami
  • 367,544
  • 15
  • 269
  • 518
  • IPC::Run3 or IPC::Run don't seem to be in my corelist. I would rather stick to corelist for the moment. Is IPC::Cmd any good? – 719016 Feb 05 '14 at 16:56
7

The error parameter to IPC::Open3::open3 should not be undefined. The synopsis for IPC::Open3 uses the Symbol::gensym function to pre-initialize the error argument:

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

The input and output parameters can be replaced with autogenerated filehandles, so it is OK to pass undef for those arguments.

Of course the least verbose option to satisfy perlcritic here is

my @o = `ls 2>/dev/null`   ## no critic
mob
  • 117,087
  • 18
  • 149
  • 283
  • 1
    The least verbose option is to ignore this critic when you want the error to appear on STDERR anyway! – ikegami Feb 05 '14 at 17:51
  • `my @o = <$r>; my @e = <$e>;` can deadlock. They need to be replaced with IO::Select if you're going to keep using `open3`. – ikegami Feb 08 '14 at 16:25