Subject: | [PATCH] Add logging when a child exits abnormally |
The attached patch adds some additional logging when a child exits unexpectedly. In our case, we had some code segfault but nothing got logged.
Unfortunately, I didn't write any tests, but I did test this on a test server here. The test suite didn't have anything I could easily extend to test this.
Subject: | net-server.patch |
diff -ru Net-Server-2.007/lib/Net/Server/PreFork.pm Net-Server-2.007.new/lib/Net/Server/PreFork.pm
--- Net-Server-2.007/lib/Net/Server/PreFork.pm 2013-01-10 01:16:20.000000000 -0600
+++ Net-Server-2.007.new/lib/Net/Server/PreFork.pm 2013-07-09 14:43:16.749470956 -0500
@@ -255,17 +255,20 @@
@{ $prop }{qw(last_checked_for_dead last_checked_for_waiting last_checked_for_dequeue last_process last_kill)} = (time) x 5;
+ my $reaper = sub {
+ while ( defined( my $chld = waitpid( -1, WNOHANG ) ) ) {
+ last unless $chld > 0;
+ $self->{'reaped_children'}->{$chld} = $?
+ ; # We'll deal with this in coordinate_children to avoid a race
+ }
+ };
+
register_sig(
PIPE => 'IGNORE',
INT => sub { $self->server_close() },
TERM => sub { $self->server_close() },
HUP => sub { $self->sig_hup() },
- CHLD => sub {
- while (defined(my $chld = waitpid(-1, WNOHANG))) {
- last unless $chld > 0;
- $self->{'reaped_children'}->{$chld} = 1; # We'll deal with this in coordinate_children to avoid a race
- }
- },
+ CHLD => $reaper,
QUIT => sub { $self->{'server'}->{'kind_quit'} = 1; $self->server_close() },
TTIN => sub { $self->{'server'}->{$_}++ for qw(min_servers max_servers); $self->log(3, "Increasing server count ($self->{'server'}->{'max_servers'})") },
TTOU => sub { $self->{'server'}->{$_}-- for qw(min_servers max_servers); $self->log(3, "Decreasing server count ($self->{'server'}->{'max_servers'})") },
@@ -274,10 +277,7 @@
$self->register_sig_pass;
if ($ENV{'HUP_CHILDREN'}) {
- while (defined(my $chld = waitpid(-1, WNOHANG))) {
- last unless $chld > 0;
- $self->{'reaped_children'}->{$chld} = 1;
- }
+ $reaper->();
}
while (1) {
@@ -345,9 +345,9 @@
# deleted SIG{'CHLD'} reaped children
foreach my $pid (keys %{ $self->{'reaped_children'} }) {
- delete $self->{'reaped_children'}->{$pid}; # delete each pid one by one to avoid another race
+ my $exit = delete $self->{'reaped_children'}->{$pid}; # delete each pid one by one to avoid another race
next if ! $prop->{'children'}->{$pid};
- $self->delete_child($pid);
+ $self->delete_child($pid, $exit);
}
# re-tally the possible types (only twice a minute)
@@ -431,7 +431,7 @@
### delete_child and other modifications contributed by Rob Mueller
sub delete_child {
- my ($self, $pid) = @_;
+ my ($self, $pid, $exit) = @_;
my $prop = $self->{'server'};
my $child = $prop->{'children'}->{$pid};
@@ -442,6 +442,18 @@
return if ! exists $prop->{'children'}->{$pid}; # Already gone?
+ # This means there was some sort of abnormal exit for the child, like a
+ # segfault.
+ if ($exit) {
+ my $status = $exit >> 8;
+ my $signal = $exit & 127;
+ my $message = "Child process $pid exited with status $status";
+ $message .= " - signal was $signal"
+ if $signal;
+
+ $self->log(1, $message);
+ }
+
my $status = $child->{'status'} || $self->log(2, "No status for $pid when deleting child");
--$prop->{'tally'}->{$status} >= 0 || $self->log(2, "Tally for $status < 0 deleting pid $pid");
$prop->{'tally'}->{'time'} = 0 if $child->{'hup'};