in reply to Inexplicable ECHILD

The weird part is that the die at the end actually executes. How can this be?
Because you're using $! when it isn't meaningful. $! is only meaningful right after a failure in a system call. Anything else may set $! to whatever it wants. Only use $! right after a failing system call.

Replies are listed 'Best First'.
Re^2: Inexplicable ECHILD
by ikegami (Patriarch) on Aug 11, 2010 at 16:18 UTC
    That's not true. Even if he did it properly (say by adding next if @ready; before the first die), he'd see the same behaviour. waitpid unavoidably overwrites $!=EINTR with $!=ECHLD between the time select reports an error and the program checks the cause of the error.
    ... use Errno qw( EINTR ); sub reaper { local ($!,$^E,$@); 1 while waitpid -1,&POSIX::WNOHANG != -1; $SIG{CHLD} = \&reaper; } $SIG{CHLD} = \&reaper; ... while (1) { my @ready = $select->can_read(); if (!@ready) { next if $! == EINTR; die "select: $!"; } handle($_) foreach @ready; }

    Update: Added code.

Re^2: Inexplicable ECHILD ($!)
by tye (Sage) on Aug 11, 2010 at 16:12 UTC

    No. The OP is checking $! very soon (in time) after a failing system call (select inside can_read() from IO::Select). The signal handler adds a race condition that has little to do with checking $! at the wrong time.

    Granted, there is a small chance that $select->count() might (indirectly) trigger the setting of $! or that can_read() could return an empty list w/o select having failed, but the source of the former risk is actually what avoids the latter risk (and the former risk seems slight).

    The code could certainly be clearer on what was expected to have set $!. Saving off with something like $err= $!; immediately after the failure would add clarity. But it wouldn't eliminate the race condition and so wouldn't really fix the actual problem described.

    - tye