nusoff has asked for the wisdom of the Perl Monks concerning the following question:

Hello Perl Monks. I have an issue with IPC::Open3, IPC::Open2 modules. When I running my script through wperl.exe, instead of perl.exe, the program hangs up if terminal window not opened.
open3: Can't call method "close" on an undefined value at C:/perl/lib/ +IPC/Open3.pm line 368. open3: Can't call method "close" on an undefined value at C:/perl/lib/ +IPC/Open3.pm line 368. while executing "::perl::CODE(0x18627b4)" invoked from within ".b invoke " invoked from within ".b instate {pressed !disabled} { .b state !pressed; .b invoke } " (command bound to event)
main.pl:
use strict; use Tkx; use IPC::Open3; my $mw = Tkx::widget->new('.'); my $tw = $mw->new_text(); my $bt = $mw->new_ttk__button( -text => 'retrieve', -command => sub { my( $pid, $wtr, $rdr, $err ); $pid = open3( $wtr, $rdr, $err, 'dir' ); $tw->insert( 'end', scalar do { local $/; <$rdr> } ); }, ); Tkx::pack( $tw ); Tkx::pack( $bt ); Tkx::MainLoop;
But perl.exe works pretty.

Replies are listed 'Best First'.
Re: IPC::Open3, wperl issue
by Anonymous Monk on Aug 19, 2009 at 08:49 UTC
      thank you
Re: IPC::Open3, wperl issue
by thospel (Hermit) on Jan 20, 2012 at 13:03 UTC
    I recently ran into the same problem and found this node. Before giving up I investigated further and decided that the standard answer (that this has to do with problems of wperl with STDERR) is incorrect or at least outdated. The problem is actually caused by open3 trying to set up a handle for STDIN. If you follow the code it turns out that in the end it does open(IN, "<&GLOB") where GLOB is a glob copy of STDIN. This fails under wperl (probably because STDIN is not sufficiently set up, I didn't trace that further). With that in mind I tried to set up a fake STDIN before doing the call and that seems to work as a workaround:
    #!/usr/bin/perl -w use strict; use IPC::Open3; open(STDIN, "<", "NUL") || die "open NUL: $!"; local (*IN,*OUT,*ERR); my $pid = open3(\*IN, \*OUT, \*ERR, "wperl", q(-le), q(my $in = <STDIN +>; print $in+3; print STDERR $in+5)); print IN "5\n"; close IN; my $line = <OUT>; print "Out=$line"; $line = <ERR>; print "Err=$line";
    And then:
    wperl program > out 2>&1 type out
    gives
    Out=8 Err=10
    Setting a global STDIN in the outer wperl is no great loss since it is not typically connected to anything anyways. If you want to be able to maybe use the STDIN of the outer wperl in case it is available I suppose you can replace the initial open by something like
    { open(my $dummy, "<&STDIN") || open(STDIN, "<", "NUL") || die "open + NUL: $!"; }