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

Hello.

I have a script for downloading bunch of data from some servers.

For each server I start ssh via IPC::Open2 like this:

my $pid = open2($rfh, $wfh, "ssh $opts $hostspec $cmd");

Then I download all data in loop via select() (4 arg version). When some ssh dies, I need to modify some program structures (same applies for INT/TERM signal). So I decided I will do it right after select() via self-pipe trick (described in NOTES in linux select(2) manpage).

### Self-pipe init. pipe(SIGRD, SIGWR); # Make SIGRD non-blocking. vec($rin, fileno SIGRD, 1) = 1;

CHLD handler does just this (INT/TERM handlers sets $term variable in addition):

my $byte = 1; syswrite(SIGWR, $byte, 1);

This is top of the main while loop.

my $nfound = select($rout = $rin, $wout = $win, undef, undef); # Check $nfound for errors. if(vec($rout, fileno SIGRD, 1)) { my $byte; while(sysread(SIGRD, $byte, 1)) { if($term) { # INT/TERM arrived, kill sshs, modify some data, ... $term = 0; } else { # CHLD arrived, do waitpid(), modify some data, ... } }

After I do waitpid() I need to check $? if ssh exited with error. However in description of $? in perlvar is stated: If you have installed a signal handler for "SIGCHLD", the value of $? will usually be wrong outside that handler. My question is why it will be wrong when I will use it just after waitpid()? Thank you.

Replies are listed 'Best First'.
Re: $? outside SIGCHLD handler
by ikegami (Patriarch) on Sep 04, 2009 at 19:37 UTC

    ug, use IO::Select. It's a thin wrapper over select that's *much* easier to use than the underlying function.

    You didn't show your signal handler. If it calls wait or waitpid, don't call wait or waitpid outside of the handler. Save the result from the handler, if you need to.

    my %reaped; $SIG{CHLD} = sub { my $pid = wait(); $reaped{$pid} = $?; }; # When reading from read ready handle returns eof, my $exit_code = delete $reaped{$pid_associated_with_handle};
      Hello.

      Sorry for long delay, I had no access to internet during weekend.

      I'll probably switch to IO::Select later, select() code works fine so far.

      Code for CHLD handler is after "CHLD handler does just this ..." in my original post (No wait()/waitpid() calls inside).

      I was just confused by sentence from "perlvar" (see end of orig post).

        I forgot to log in. The reply above is mine.