I'm writing scripts which need to execute some other programs, and look at the stdout and stderr from said calls. My scripts, in turn, are to be called by a 3rd party, closed source program.

I've been using IPC::Open3 for this, and things work great when run from the commandline. But when invoked by the 3rd party program, the call to open3 fails with the following messsage: open3: Can't call method "close" on an undefined value at c:/apps/perl/lib/IPC/Open3.pm line 368.

I whipped up a small test script to illustrate the problem. The 3rd party program doesn't display stdout or stderr, hence why I'm writing everything to files. Also, the "#------#" lines are just to show where the script starts and ends in this post, and are not present in the script

#------# Begin code for test_open3.pl #!c:/apps/perl/bin/perl use IPC::Open3 qw( open3 ); use strict; use warnings; $| = 1; open DBG, ">debug2.log" or die $!; eval { my @pids; my @cmd1 = ( 'c:/Program Files/TortoiseSVN/bin/svn.exe', '--ve +rsion', '-- quiet'); my $nul = $^O eq 'MSWin32' ? 'nul' : '/dev/null'; open(CHILD_STDERR, '>', 'error.txt') or die "Could not open CH +ILD_STDERR for writing ($!)"; open(CHILD_STDOUT, '>', 'out.txt') or die "Could not open CHIL +D_STDOUT for writing ($!)"; push @pids, open3(undef, '>&CHILD_STDOUT', '>&CHILD_STDERR', @ +cmd1); waitpid($_, 0) for @pids; print "Child exited with value ", $? >> 8, "\n"; #close(CHILD_STDIN) or die "Could not clost STDIN ($!)"; close CHILD_STDOUT or die "Could not close STDOUT"; open(CHILD_STDOUT, '<', 'out.txt') or die "Could not open CHILD_ST +DOUT for reading ($!)"; my @out = <CHILD_STDOUT>; close CHILD_STDOUT or die "Could not close STDOUT ($!)"; close CHILD_STDERR or die "Could not close STDERR"; open(CHILD_STDERR, '<', 'err.txt') or die "Could not open CHILD_ST +DERR for reading ($!)"; my @err = <CHILD_STDERR>; close CHILD_STDERR or die "Could not close STDERR ($!)"; print "----OUT----\n", join("\n", @out), "----OUT----\n"; print "----ERR----\n", join("\n", @err), "----ERR----\n"; print DBG "Done!\n"; }; if ($@) { print DBG $@; close DBG; exit 1; } close DBG; #------#

The above code yields open3: Can't call method "close" on an undefined value at c:/apps/perl/lib/IPC/Open3.pm line 368. inside the debug2.log file.

I tried a slightly different approach with this test script:

#------# begin code for test9.pl #!c:/apps/perl/bin/perl use IPC::Open3 qw( open3 ); use strict; use warnings; open DBG, ">debug2.log" or die $!; eval { my @cmd1 = ( 'c:/Program Files/TortoiseSVN/bin/svn.exe', '--versio +n', '--quiet'); print "Running ", join(" ", map { "'$_'" } @cmd1), "\n"; open my $old_stdout, '>&', STDOUT or die "Couldn't dup stdout! ($! +)"; open my $old_stderr, '>&', STDERR or die "Couldn't dup stderr! ($! +)"; open STDOUT, '>', 'out.txt' or die "Couldn't redirect stdout to fi +le! ($!)"; open STDERR, '>', 'err.txt' or die "Couldn't redirect stderr to fi +le! ($!)"; system(@cmd1); close STDOUT; close STDERR; open STDOUT, '>&', $old_stdout or die "Could not re-connect to std +out! ($!)"; open STDERR, '>&', $old_stderr or die "Could not re-connect to std +err! ($!)"; open FH, '<', 'out.txt' or die "Could not open out.txt! ($!)"; open FH2, '<', 'err.txt' or die "Could not open err.txt! ($!)"; my ($out, $err); { local $/; $out = <FH>; $err = <FH2>; } close FH; close FH2; print "----OUT----\n", $out, "\n----OUT----\n"; print "----ERR----\n", $err, "\n----ERR----\n"; #print join("\n", @err), "\n"; }; if ($@) { print DBG $@; exit 1; } close DBG; #------#

...and that also works just fine under the commandline, but bombs when invoked by the 3rd party program. This time, the error message in debug2.log is: Couldn't dup stdout! (Permission denied) at d:/users/jdoe/test9.pl line 12.

I'm trying hard to avoid invoking the shell. The scripts need to run under a wide variety of systems: ActiveState Perl, Cygwin Perl, actual Unix systems, ActiveState Perl running under Cygwin, etc. This makes using backquotes a real pain since it's hard to know what shell will be executed and thus what rules to use when shell escaping a command.

UPDATE: Forgot to actually ask the proper question: The 3rd party program seems to be doing something funky to stdout (and maybe stderr and/or stdin) which is causing open3 to bomb. Does anyone have any suggestions on how to cope with this, or a different way to tackle the problem without invoking the shell? I'd also appreciate any insight as to what could be going on, even if you don't have suggestions for a solution. I couldn't find anything on google or perlmonks' search, though maybe my search-fu is weak.

UPDATE 2: Running perl --version yields:

This is perl, v5.8.9 built for MSWin32-x86-multi-thread (with 13 registered patches, see perl -V for more detail) Copyright 1987-2008, Larry Wall Binary build 828 [294165] provided by ActiveState http://www.ActiveSta +te.com Built Dec 8 2010 16:51:11 Perl may be copied only under the terms of either the Artistic License + or the GNU General Public License, which may be found in the Perl 5 source ki +t. Complete documentation for Perl, including FAQ lists, should be found +on this system using "man perl" or "perldoc perl". If you have access to + the Internet, point your browser at http://www.perl.org/, the Perl Home Pa +ge.


In reply to IPC::Open3 Fails Under Win32 When Perl Is Called By Another Program by SirRobin

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.