Kyle R. Burton on 31 Oct 2003 22:43:02 -0500 |
> > eval { $cmd_pid=open3(\*IN, \*OUT, \*ERR, @cmd); }; > > if($@ =~ /exec/){ > > print "\@ is $@\n"; > > $cmd_errstr = $@; > > $cmd_retval = "-1"; > > die; > > }; > > ... > > oh, i forgot: the duplicates happen if you take out the call to die(), > but not if you leave it in, which is why i'm thinking this is some > wierdness involved with a fork(). Well, I just hacked togeather some test code and it looks like open3 first creates pipes appropriately, then forks, and then attempts to exec the command. Since the fork has already happened, a failure of exec(), now in the child, can only be reported to it's std{out,err}. I don't get mixed output, I get synchronous output. The only trick is to exit in the child (if $pid is zero/undef) _after_ the implied exec (so if the exec fails in the child, the child still exits). HTH Kyle use strict; use warnings; use IPC::Open3; $|++; #my @cmd = qw(ls -ld /tmp); # works #my @cmd = qw(ls -l /adsftmp); # command errors after successful fork+exec my @cmd = qw(addfadf -l /tmp); # fails exec after fork my $pid = ''; my $sigpipe = 0; $SIG{PIPE} = sub { print STDERR "got SIGPIPE\n"; $sigpipe++; }; my($in,$out,$err) = ('','',''); eval { $pid = open3($in,$out,$err,@cmd); unless ( $pid ) { print "\$\$=$$ pid=$pid Whoa, the exec failed?: $!\n"; } print "\$\$=$$ pid=$pid open3 returned\n"; }; print "\$\$=$$ pid=$pid back outside the eval...\n"; if ($@) { die "\$\$=$$ pid=$pid whoops: $@"; } print "\$\$=$$ pid=$pid no exception, everthing seems to have worked, proceding to read \n"; sleep 1; readfh_nonblock("out",$out); sleep 1; readfh_nonblock("err",$err); foreach my $fh ($in,$out,$err) { close $fh if $fh; } print "finished, closing file handles\n"; print " pid=$pid\n"; print " sigpipe=$sigpipe\n"; # non-blocking read loop sub readfh_nonblock { my($name,$fh) = @_; return unless $fh; print "$name:\n"; print " pid=$pid\n"; print " sigpipe=$sigpipe\n"; print "$name===>\n"; while (1) { my $buff; my $nr = sysread($fh,$buff,1024); unless (defined $nr) { print "Error reading from handle $name: $!\n"; last; } last unless $nr; print $buff; } print "<===$name\n"; } -- ------------------------------------------------------------------------------ Wisdom and Compassion are inseparable. -- Christmas Humphreys mortis@voicenet.com http://www.voicenet.com/~mortis ------------------------------------------------------------------------------ ___________________________________________________________________________ Philadelphia Linux Users Group -- http://www.phillylinux.org Announcements - http://lists.phillylinux.org/mailman/listinfo/plug-announce General Discussion -- http://lists.phillylinux.org/mailman/listinfo/plug
|
|