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

Please be patient... new user Open3 problem... I have attempted to make a module for myself to do generic system calls, this module returns a hash reference with the pid,stdout,stderr,return status,and command. It worked fine with a simple command like `cat` but hangs with a `scp`. I have noted that the documentation explains this problem, but lack the skills to implement the IO::Select module or the 4 argument select statement to fix the problem.... I ended abandoning my module and used the NET::SCP module from CPAN instead... just to figure out that it suffers from the same problem that my module has. If anyone has a good example for me to checkout or has some experience with this please let me know. Thanks.

Replies are listed 'Best First'.
Re: Fun with Open3
by ikegami (Patriarch) on Jul 21, 2006 at 22:38 UTC
      Thanks, I will have a look.
Re: Fun with Open3
by zentara (Cardinal) on Jul 22, 2006 at 12:50 UTC
    Here is an example which I was given when asking the same question a few years ago.
    #!/usr/bin/perl # sgifford of perlmonks # The reason for your problem is because you're not using # IO::Select quite right. You're passing a timeout of 0 to # can_read, which asks it to return immediately if there is # no data ready yet. What I think you want to do is create # one IO::Select object with both handles, then ask it to # wait until one or both have something ready to read. # Something like this: # It's only drawback is it only outputs 1 line of bc output # so it errs on something like 234^12345 (which outputs a big number) use warnings; use strict; use IPC::Open3; use IO::Select; #interface to "bc" calculator my $pid = open3(\*WRITE, \*READ,\*ERROR,"bc"); my $sel = new IO::Select(); $sel->add(\*READ); $sel->add(\*ERROR); my($error,$answer)=('',''); while(1){ print "Enter expression for bc, i.e. 2 + 2\n"; chomp(my $query = <STDIN>); #send query to bc print WRITE "$query\n"; foreach my $h ($sel->can_read) { my $buf = ''; if ($h eq \*ERROR) { sysread(ERROR,$buf,4096); if($buf){print "ERROR-> $buf\n"} } else { sysread(READ,$buf,4096); if($buf){print "$query = $buf\n"} } } } waitpid($pid, 1); # It is important to waitpid on your child process, # otherwise zombies could be created.

    I'm not really a human, but I play one on earth. Cogito ergo sum a bum