I'm trying to catch errors from tasks forked with Wheel::Run - I'm using childtest3 as an example and preforming "exit 3 if $task eq 'two';" in the do_stuff sub. I've put an ErrorEvent in place etc - seems to me it always error exits with read (as described in 'Run.pm' pod), but never seems to exit with my error code. I want to be able to tell is on of my many concurrent tasks errors and why?
Operating systems report error and/or exit codes as part of SIGCHLD processing. That is, the exit code will arrive on a SIGCHLD, not as part of a read error on a pipe.
Wheel::Run does not handle SIGCHLD for you. This was decided for two reasons:
1. Currently sessions can only register a single handler for any given signal. If Wheel::Run instances were to register their own handlers, each would clobber the next. This may change, but...
2. ... even so, it would be inefficient to dispatch SIGCHLD to N Wheel::Run instances only to have N-1 of them ignore it.
Therefore you must handle the SIGCHLD yourself and match its PID against the Wheel::Run instance's. The easiest way is to keep a hash of PIDs to wheels:
$heap->{pid_to_wheel}->{$new_wheel->PID} = $new_wheel; $heap->{id_to_wheel}->{$new_wheel->ID} = $new_wheel;
The pid_to_wheel hash allows you to match SIGCHLD PIDs to their corresponding wheels in short order. It also lets you know quickly that a SIGCHLD doesn't belong to this session.
The id_to_wheel hash lets you match events to the appropriate wheels, so you can put() responses to a child process' output, or something.
When the signal handler catches a SIGCHLD with an interesting PID, you can gather the child process' exit value from ARG2. ARG2 contains the value of $? as it appeared after waitpid() reaped the process. See `perldoc perlvar` about $? for more information about ARG2's contents.
sub sigchld_handler { my ($heap, $pid, $child_error) = @_[HEAP, ARG1, ARG2]; return unless exists $heap->{pid_to_wheel}->{$pid}; my $wheel = delete $heap->{pid_to_wheel}->{$pid}; delete $heap->{id_to_wheel}->{$wheel->ID}; print("child process $pid exited with status ", ($child_error >> 8), "\n"); }