taskd.pl: avoid displaying spurious accept failed errors
authorKyle J. McKay <mackyle@gmail.com>
Thu, 22 Aug 2013 07:39:24 +0000 (22 00:39 -0700)
committerKyle J. McKay <mackyle@gmail.com>
Thu, 22 Aug 2013 07:39:24 +0000 (22 00:39 -0700)
When taskd.pl forks a child (using the spawn subroutine), it will
eventually reap it via SIGCHLD.  This SIGCHLD will almost certainly
interrupt the accept() wait on new connections to the taskd socket
causing the accept() to return with an EINTR error which is then
reported.  Since this is actually a normal condition in this case,
the error is simply spurious and should not be shown.

There are two problems that must be fixed to address this:

1) The SIGCHLD handler must preserve the Perl errno ($!) value so
   that the EINTR error from accept() can be reliably detected.  This
   is accomplished by 'local $!' in the SIGCHLD handler.  Otherwise
   when the SIGCHLD handler calls waitpid() the $! that held the result
   of the accept() call (which will be EINTR in this case) will be
   replaced with the result of waitpid().  Since waitpid() is called in
   a loop until it fails that result will usually be ECHILD after the
   last zombie has been reaped.

2) When the accept() call fails and an EINTR state is detected, just
   silently retry instead of displaying a spurious error message.  It
   was previously not possible to do this reliably without the fix
   from (1).

With these fixes the spurious "accept failed: ..." messages are no
longer output by taskd.pl.

taskd/taskd.pl

index 15d6251..f06dc81 100755 (executable)
@@ -35,6 +35,7 @@ use Girocco::Notify;
 use Girocco::Project;
 use Girocco::User;
 use Socket;
+use Errno;
 
 $| = 1;
 
@@ -52,6 +53,7 @@ chmod 0666, $NAME or die "chmod: $!";
 
 use POSIX ":sys_wait_h";
 sub REAPER {
+       local $!;
        my $child;
        my $waitedpid;
        while (($waitedpid = waitpid(-1, WNOHANG)) > 0) {
@@ -115,7 +117,7 @@ sub ref_change {
 
 while (1) {
        unless (accept(Client, Server)) {
-               logmsg "accept failed: $!";
+               logmsg "accept failed: $!" unless $!{EINTR};
                next;
        }
        logmsg "connection on $NAME";