http://qs321.pair.com?node_id=767504

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

Hello wise monks. Many thanks for helping me identify the source of the problem that is the cmd.exe QuickEdit mode last time.

But now I need your wisdom again.

Suppose we have two perl files, parent.pl and child.pl. We start by running parent.pl, which will start another process to run child.pl. How do I propagate the errors in child.pl to parent.pl.

This is parent.pl
#!/usr/bin/perl use Win32::Process; for (1..3) { eval { print "$_\n"; Win32::Process::Create(my $proc, $^X, "perl child.pl", 0, 0, "."); }; if ($@) { if (index($@, 'Custom Exception') == 0) { print "Caught exception: $@"; next; } else { die $@; } } }

And this is child.pl
#!/usr/bin/perl die 'Custom Exception';

As you can see, what I'm trying to do is to iterate to the next loop (instead of simply die-ing) when a custom exception is caught. This works if the code inside the eval block is still in same process. However, eval does not seem to be able to catch errors that are in another process. I have tried some modules like Error and Error::TryCatch as well but nothing works.

Replies are listed 'Best First'.
Re: eval-ling code in another process
by targetsmart (Curate) on Jun 02, 2009 at 09:15 UTC
    How do I propagate the errors in child.pl to parent.pl.

    use system for that purposes. it will return the status of the child to the parent


    Vivek
    -- In accordance with the prarabdha of each, the One whose function it is to ordain makes each to act. What will not happen will never happen, whatever effort one may put forth. And what will happen will not fail to happen, however much one may seek to prevent it. This is certain. The part of wisdom therefore is to stay quiet.
Re: eval-ling code in another process
by lakshmananindia (Chaplain) on Jun 02, 2009 at 09:46 UTC

    Additional Information

    If you are using system to get the exit status, the normal way is to shift the $? right by 8 times

    But man perlport suggest as follows

    In general, do not assume the UNIX/POSIX semantics that you can shift $? right by eight to get the exit value, or that "$? & 127" would give you the number of the signal that terminated the program, or that "$? & 128" would test true if the program was terminated by a coredump. Instead use the POSIX W*() interfaces: for example, use IFEXITED($?) and WEXIT-VALUE($?) to test for a normal exit and the exit value, WIFSIGNALED($?) and WTERMSIG($?) for a signal exit and the signal.

    --Lakshmanan G.

    The great pleasure in my life is doing what people say you cannot do.


Re: eval-ling code in another process
by ikegami (Patriarch) on Jun 02, 2009 at 14:42 UTC

    The only thing that can be passed from the child to the parent is its exit code and streams of bytes in file handles (usually pipes attached to the child's STDOUT and STDERR). Specifically, the OS knows nothing of exceptions.

    If you wish to recreate in the parent an object that existed in the child, you'll need to develop a protocol to transmit the necessary information to do so, and both your child and parent will need to adhere to that protocol.

Re: eval-ling code in another process
by KHLeow (Novice) on Jun 02, 2009 at 10:12 UTC
    Then how do I know if $? is the custom exception I have been looking for? All I get is WEXITSTATUS($?)=255 for any 'die' signal.
      Consider replacing
      die "Something informative";
      with
      warn "Something informative"; exit $customCodeToDetectInParent;

      --
      use JAPH;
      print JAPH::asString();

      die only writes its "exception" to the standard error stream, so you'll need to capture that output. In Unix you can do this using a piped open like open my $fh, 'othercommand 2>&1 |'; and then reading $fh. Or you could even do my $response = `othercommand 2>&1`; and parse out the result. Not sure if that works in Windows. You could also try IPC::Open3. I don't think Win32::Process will let you capture that.