You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spamassassin.apache.org by mm...@apache.org on 2012/05/14 18:31:09 UTC
svn commit: r1338278 - in /spamassassin/trunk:
lib/Mail/SpamAssassin/Logger/Syslog.pm spamd/spamd.raw
Author: mmartinec
Date: Mon May 14 16:31:09 2012
New Revision: 1338278
URL: http://svn.apache.org/viewvc?rev=1338278&view=rev
Log:
Bug 6745: spamd crashes because of memory problems in Logger.pm
Modified:
spamassassin/trunk/lib/Mail/SpamAssassin/Logger/Syslog.pm
spamassassin/trunk/spamd/spamd.raw
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Logger/Syslog.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Logger/Syslog.pm?rev=1338278&r1=1338277&r2=1338278&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Logger/Syslog.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Logger/Syslog.pm Mon May 14 16:31:09 2012
@@ -167,17 +167,21 @@ sub log_message {
}
$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)) {
Modified: spamassassin/trunk/spamd/spamd.raw
URL: http://svn.apache.org/viewvc/spamassassin/trunk/spamd/spamd.raw?rev=1338278&r1=1338277&r2=1338278&view=diff
==============================================================================
--- spamassassin/trunk/spamd/spamd.raw (original)
+++ spamassassin/trunk/spamd/spamd.raw Mon May 14 16:31:09 2012
@@ -589,6 +589,7 @@ my $timeout_tcp; # socket timeo
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'};
@@ -1033,6 +1034,8 @@ while (1) {
# 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++) {
@@ -2523,7 +2526,8 @@ sub child_handler {
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 (;;) {
@@ -2534,12 +2538,23 @@ sub child_handler {
#
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};
@@ -2550,15 +2565,10 @@ sub child_handler {
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 {