ensure that quickly-terminating master subprocesses do not escape our notice
authorDaniel Kahn Gillmor <dkg@fifthhorseman.net>
Wed, 27 Oct 2010 04:18:03 +0000 (00:18 -0400)
committerDaniel Kahn Gillmor <dkg@fifthhorseman.net>
Wed, 27 Oct 2010 04:18:03 +0000 (00:18 -0400)
Crypt/Monkeysphere/MSVA.pm
Net/Server/MSVA.pm

index bff6088722a46c8b542049abacbc1baf184e0e19..ee712361d7a0655a135a019044781f44f8fb482e 100755 (executable)
     return $status, $ret;
   }
 
+  sub pre_loop_hook {
+    my $self = shift;
+    my $server = shift;
+
+    $self->spawn_master_subproc($server);
+    if (exists $self->{child_pid} &&
+        $self->{child_pid} != 0) {
+      my $val;
+      while (defined($val = POSIX::waitpid(-1, POSIX::WNOHANG)) && $val > 0) {
+        msvalog('debug', "waitpid on %d: got %d\n", $self->{child_pid}, $val);
+        if ($val == $self->{child_pid}) {
+          $self->master_subprocess_died($server, $?);
+        }
+      }
+    }
+  }
+
+  sub master_subprocess_died {
+    my $self = shift;
+    my $server = shift;
+    my $subproc_return = shift;
+
+    my $exitstatus = POSIX::WEXITSTATUS($subproc_return);
+    msvalog('verbose', "Subprocess %d terminated; exiting %d.\n", $self->{child_pid}, $exitstatus);
+    $server->set_exit_status($exitstatus);
+    $server->server_close();
+  }
+
   sub child_dies {
     my $self = shift;
     my $pid = shift;
     } elsif (exists $self->{child_pid} &&
              ($self->{child_pid} == 0 ||
               $self->{child_pid} == $pid)) {
-      my $exitstatus = POSIX::WEXITSTATUS($?);
-      msvalog('verbose', "Subprocess %d terminated; exiting %d.\n", $pid, $exitstatus);
-      $server->set_exit_status($exitstatus);
-      $server->server_close();
+      $self->master_subprocess_died($server, $?);
     }
   }
 
       $server->server_close();
     }
     $self->port($port);
+    $self->{updatemonitor} = Crypt::Monkeysphere::MSVA::Monitor->new($logger);
+  }
+
+  sub spawn_master_subproc {
+    my $self = shift;
+    my $server = shift;
 
     if ((exists $ENV{MSVA_CHILD_PID}) && ($ENV{MSVA_CHILD_PID} ne '')) {
       # this is most likely a re-exec.
       $self->{child_pid} = $ENV{MSVA_CHILD_PID} + 0;
     } elsif ($#ARGV >= 0) {
       $self->{child_pid} = 0; # indicate that we are planning to fork.
+      # avoid ignoring SIGCHLD right before we fork.
+      $SIG{CHLD} = 'DEFAULT';
       my $fork = fork();
       if (! defined $fork) {
         msvalog('error', "could not fork\n");
       # ssh-agent.  maybe avoid backgrounding by setting
       # MSVA_NO_BACKGROUND.
     };
-
-    $self->{updatemonitor} = Crypt::Monkeysphere::MSVA::Monitor->new($logger);
   }
 
   sub extracerts {
index 805700b4d9c0adeac630aa2dd3d00a83a38f8fea..07e43ee580a4b61b3e75be3061f318c33faaad11 100644 (file)
     $msva->post_bind_hook($self, @_);
   }
 
+  sub pre_loop_hook {
+    my $self = shift;
+    $msva->pre_loop_hook($self, @_);
+  }
+
   sub set_exit_status {
     my $self = shift;
     $exit_status = shift;