1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
|
Index: spamassassin-3.3.2/lib/Mail/SpamAssassin/Logger/Syslog.pm
===================================================================
--- spamassassin-3.3.2.orig/lib/Mail/SpamAssassin/Logger/Syslog.pm 2013-01-22 20:19:12.000000000 -0800
+++ spamassassin-3.3.2/lib/Mail/SpamAssassin/Logger/Syslog.pm 2013-01-22 20:19:57.000000000 -0800
@@ -148,17 +148,21 @@
}
$msg = $timestamp . ' ' . $msg if $timestamp ne '';
- # important: do not call syslog() from the SIGCHLD handler
- # child_handler(). otherwise we can get into a loop if syslog()
- # forks a process -- as it does in syslog-ng apparently! (bug 3625)
- $Mail::SpamAssassin::Logger::LOG_SA{INHIBIT_LOGGING_IN_SIGCHLD_HANDLER} = 1;
+# no longer needed since a patch to bug 6745:
+# # important: do not call syslog() from the SIGCHLD handler
+# # child_handler(). otherwise we can get into a loop if syslog()
+# # forks a process -- as it does in syslog-ng apparently! (bug 3625)
+# $Mail::SpamAssassin::Logger::LOG_SA{INHIBIT_LOGGING_IN_SIGCHLD_HANDLER} = 1;
+
my $eval_stat;
eval {
syslog($level, "%s", $msg); 1;
} or do {
$eval_stat = $@ ne '' ? $@ : "errno=$!"; chomp $eval_stat;
};
- $Mail::SpamAssassin::Logger::LOG_SA{INHIBIT_LOGGING_IN_SIGCHLD_HANDLER} = 0;
+
+# no longer needed since a patch to bug 6745:
+# $Mail::SpamAssassin::Logger::LOG_SA{INHIBIT_LOGGING_IN_SIGCHLD_HANDLER} = 0;
if (defined $eval_stat) {
if ($self->check_syslog_sigpipe($msg)) {
Index: spamassassin-3.3.2/spamd/spamd.raw
===================================================================
--- spamassassin-3.3.2.orig/spamd/spamd.raw 2013-01-22 20:19:12.000000000 -0800
+++ spamassassin-3.3.2/spamd/spamd.raw 2013-01-22 20:19:57.000000000 -0800
@@ -588,6 +588,7 @@
my $timeout_child; # processing timeout (headers->finish), 0=no timeout
my $clients_per_child; # number of clients each child should process
my %children; # current children
+my @children_exited;
if ( defined $opt{'max-children'} ) {
$childlimit = $opt{'max-children'};
@@ -1031,6 +1032,8 @@
# child_handler() if !$scaling || am_running_on_windows();
child_handler(); # it doesn't hurt to call child_handler unconditionally
+ child_cleaner();
+
do_sighup_restart() if defined $got_sighup;
for (my $i = keys %children; $i < $childlimit; $i++) {
@@ -2517,7 +2520,8 @@
my ($sig) = @_;
# do NOT call syslog here unless the child's pid is in our list of known
- # children. This is due to syslog-ng brokenness -- bugs 3625, 4237.
+ # children. This is due to syslog-ng brokenness -- bugs 3625, 4237;
+ # see also bug 6745.
# clean up any children which have exited
for (;;) {
@@ -2528,12 +2532,23 @@
#
my $pid = waitpid(-1, WNOHANG);
last if !$pid || $pid == -1;
- my $child_stat = $?;
+ push(@children_exited, [$pid, $?, $sig, time]);
+ }
- if (!defined $children{$pid}) {
- # ignore this child; we didn't realise we'd forked it. bug 4237
- next;
- }
+ $SIG{CHLD} = \&child_handler; # reset as necessary, should be at end
+}
+
+# takes care of dead children, as noted by a child_handler()
+# called in a main program flow (not from a signal handler)
+#
+sub child_cleaner {
+ while (@children_exited) {
+ my $tuple = shift(@children_exited);
+ next if !$tuple; # just in case
+ my($pid, $child_stat, $sig, $timestamp) = @$tuple;
+
+ # ignore this child if we didn't realise we'd forked it. bug 4237
+ next if !defined $children{$pid};
# remove them from our child listing
delete $children{$pid};
@@ -2544,15 +2559,10 @@
my $sock = $backchannel->get_socket_for_child($pid);
if ($sock) { $sock->close(); }
}
-
- unless ($Mail::SpamAssassin::Logger::LOG_SA{INHIBIT_LOGGING_IN_SIGCHLD_HANDLER}) {
- info("spamd: handled cleanup of child pid [%s]%s: %s",
- $pid, (defined $sig ? " due to SIG$sig" : ""),
- exit_status_str($child_stat,0));
- }
+ info("spamd: handled cleanup of child pid [%s]%s: %s",
+ $pid, (defined $sig ? " due to SIG$sig" : ""),
+ exit_status_str($child_stat,0));
}
-
- $SIG{CHLD} = \&child_handler; # reset as necessary, should be at end
}
sub restart_handler {
|