in reply to Doubled print with eval and open3

The open3 doesn't throw an exception so the eval doesn't catch it. Instead test $!:

$! = undef; $pid=open3($WRITE, $READ, $ERROR, "$command"); if (length $!) { $error="Error, Could not execute $command: $!"; } else {

If there are exceptions you want to catch that can be thrown then put the eval back in and add a elsif as appropriate.


DWIM is Perl's answer to Gödel

Replies are listed 'Best First'.
Re^2: Doubled print with eval and open3
by ikegami (Patriarch) on Mar 06, 2007 at 00:03 UTC

    The open3 doesn't throw an exception so the eval doesn't catch it.

    If that's true, why is "Error, Could not executed" printed. That's part of the exception handler.

    If that's true, does that mean the following passage from IPC::Open3's docs is wrong?

    open3() returns the process ID of the child process. It doesn't return on failure: it just raises an exception matching /^open3:/. However, exec failures in the child are not detected. You'll have to trap SIGPIPE yourself.

      Hmm, interesting. I ran OP's code under a debugger as a learning exercise, and thought I'd inferred the problem. Maybe I just found a different one:

      If that's true, why is "Error, Could not executed" printed.

      On Windows it's not - there's a clue right there! Actually on Windows the OP's sample code just prints a comma. The following:

      use strict; use warnings; use IPC::Open3; use IO::Select; use POSIX ":sys_wait_h"; use Symbol; my $ERROR=gensym(); my $command="not_a_command"; my ($WRITE, $READ); my $pid; $! = undef; eval {$pid = open3($WRITE, $READ, $ERROR, "$command");}; print "pid is $pid\n" if $pid; if ($@) { print "Trapped error $@"; } elsif (length $!) { print "Detected error: $!"; } else { print "No error"; }

      prints:

      pid is 3412 Detected error: No such file or directory

      on Windows.


      DWIM is Perl's answer to Gödel
        And for FreeBSD 6.1 and Perl 5.8.8, I get
        pid is 18693 No error

        The error occured in the forked child process, so the exec or die would get sent to the file handle piped to $ERROR, and only the child's $! would be affected if the fork succeeded.

        ikegami erases the paragraph he was writting.
        Oo! I just figured it out!

        The OP must be on a system where fork is used ($^O eq 'os2' || $^O eq 'MSWin32' is false). The fork succeeds, but the exec fails. He's getting output from both the child and the parent! Fix:

        my $pid = eval { open3($WRITE, $READ, $ERROR, "$command") }; if (!$pid) { # We're in the child. # The fork succeeded, but the exec failed. POSIX::_exit($!); } ...

        Update: Oops! Looks like almut beat me to it here