Subject: | Using Open3 clobbers STDIN |
Date: | Fri, 5 Oct 2012 15:56:58 +0100 |
To: | bug-ipc-cmd [...] rt.cpan.org |
From: | Smylers <Smylers [...] stripey.com> |
Hi there. I'm finding that when IPC::Cmd uses IPC::Open3 (the default)
that the calling program's standard input is wiped. This is on Linux:
$ seq 1 5 | perl -MIPC::Cmd=run -wnE 'print "before $_"; if ($. == 3) { run command => q[date], verbose => 1 } print "after $_";'
before 1
after 1
before 2
after 2
before 3
Running [date]...
Fri Oct 5 15:35:29 BST 2012
after 3
See that run completes successfully, with "after 3" getting printed. But
the -n loop then terminates; the 4 and 5 have gone missing from STDIN.
Using IPC::Cmd the behaviour is as expected:
$ seq 1 5 | perl -MIPC::Cmd=run -wnE 'BEGIN { $IPC::Cmd::USE_IPC_RUN = 1 } print "before $_"; if ($. == 3) { run command => q[date], verbose => 1 } print "after $_";'
before 1
after 1
before 2
after 2
before 3
Running [date]...
Fri Oct 5 15:39:35 BST 2012
after 3
before 4
after 4
before 5
after 5
As it is with the simple system call, disabling IPC::Open3:
$ seq 1 5 | perl -MIPC::Cmd=run -wnE 'BEGIN { $IPC::Cmd::USE_IPC_OPEN3 = 0 } print "before $_"; if ($. == 3) { run command => q[date], verbose => 1 } print "after $_";'
before 1
after 1
before 2
after 2
before 3
Running [date]...
Fri Oct 5 15:41:13 BST 2012
after 3
before 4
after 4
before 5
after 5
When using IPC::Open3, local-izing *STDIN gives the expected output,
through a bunch of warnings:
$ seq 1 5 | perl -MIPC::Cmd=run -wnE 'print "before $_"; if ($. == 3) { local *STDIN; run command => q[date], verbose => 1 } print "after $_";'
before 1
after 1
before 2
after 2
before 3
Running [date]...
Use of uninitialized value in concatenation (.) or string at /usr/share/perl/5.14/IPC/Cmd.pm line 1594.
Could not dup 'STDIN': Invalid argument at -e line 1
Use of uninitialized value in numeric ne (!=) at /usr/share/perl/5.14/IPC/Open3.pm line 160.
Use of uninitialized value in numeric ne (!=) at /usr/share/perl/5.14/IPC/Open3.pm line 160.
close() on unopened filehandle STDIN at /usr/share/perl/5.14/IPC/Open3.pm line 80.
Fri Oct 5 15:43:22 BST 2012
Use of uninitialized value in concatenation (.) or string at /usr/share/perl/5.14/IPC/Cmd.pm line 1628.
Could not restore 'STDIN': Invalid argument at -e line 1
after 3
before 4
after 4
before 5
after 5
As does using IPC::Open3 directly, passing it null input:
$ seq 1 5 | perl -MIPC::Open3=open3 -wnE 'print "before $_"; if ($. == 3) { my ($in, $out, $err); open3 $in, $out, $err, q[date]; print <$out>; } print "after $_";'
before 1
after 1
before 2
after 2
before 3
Fri Oct 5 15:48:00 BST 2012
after 3
before 4
after 4
before 5
after 5
Or passing it a local-ized STDIN:
$ seq 1 5 | perl -MIPC::Open3=open3 -wnE 'print "before $_"; if ($. == 3) { my ($out, $err); local *STDIN; open3 *STDIN, $out, $err, q[date]; print <$out>; } print "after $_";'
before 1
after 1
before 2
after 2
before 3
Fri Oct 5 15:49:39 BST 2012
after 3
before 4
after 4
before 5
after 5
So the problem seems to be in the way IPC::Run::run is calling open3.
Let me know if I can be any more help with this.
Cheers
Smylers
--
New series of TV puzzle show 'Only Connect' (some questions by me)
Mondays at 20:30 on BBC4, or iPlayer: http://www.bbc.co.uk/onlyconnect