On Tue, Jan 06, 2004 at 11:08:51AM -0000, david.ferrington@ubs.com wrote:
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");
}