You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spamassassin.apache.org by jm...@apache.org on 2004/09/04 04:43:52 UTC

svn commit: rev 43310 - spamassassin/trunk/spamd

Author: jm
Date: Fri Sep  3 19:43:52 2004
New Revision: 43310

Modified:
   spamassassin/trunk/spamd/spamd.raw
Log:
bug 3625: syslog-ng sometimes forks from inside syslog() when syslogd is restarted, causing a SIGCHLD, which calls syslog(), and therefore causes an infinite loop of respawning spamds.  work around this.

Modified: spamassassin/trunk/spamd/spamd.raw
==============================================================================
--- spamassassin/trunk/spamd/spamd.raw	(original)
+++ spamassassin/trunk/spamd/spamd.raw	Fri Sep  3 19:43:52 2004
@@ -1676,32 +1676,22 @@
 
   # install a new handler for SIGPIPE -- this signal has been
   # found to occur with syslog-ng after syslog-ng restarts.
-  local $SIG{'PIPE'} = sub { $main::SIGPIPE_RECEIVED++ };
-
+  local $SIG{'PIPE'} = sub {
+    $main::SIGPIPE_RECEIVED++;
+    # force a log-close.
+    closelog();
+  };
+
+  # 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)
+  $main::INHIBIT_LOGGING_IN_SIGCHLD_HANDLER = 1;    #{
   eval { syslog( 'info', "%s", $msg ); };
+  $main::INHIBIT_LOGGING_IN_SIGCHLD_HANDLER = 0;    #}
 
   if ($@) {
-    if ($main::SIGPIPE_RECEIVED) {
-
-      # SIGPIPE received when writing to syslog -- close and reopen
-      # the log handle, then try again.
-      closelog();
-      openlog_for_spamd();
-      syslog( 'debug', "%s", "syslog reopened" );
-      syslog( 'info', "%s", $msg );
-
-      # now report what happend
-      $msg = "SIGPIPE received, reopening log socket";
-      warn "logmsg: $msg\n" if $opt{'debug'};
-      syslog( 'warning', "%s", $msg );
-
-      # if we've received multiple sigpipes, logging is probably
-      # still broken.
-      if ( $main::SIGPIPE_RECEIVED > 1 ) {
-        warn "logging failure: multiple SIGPIPEs received\n";
-      }
-
-      $main::SIGPIPE_RECEIVED = 0;
+    if (check_syslog_sigpipe($msg)) {
+      # dealt with
     }
     else {
       warn "syslog() failed: $@"; # includes a \n
@@ -1713,6 +1703,39 @@
       }
     }
   }
+  else {
+    check_syslog_sigpipe($msg);       # check for SIGPIPE anyway (bug 3625)
+  }
+}
+
+sub check_syslog_sigpipe {
+  my ($msg) = @_;
+
+  if ($main::SIGPIPE_RECEIVED)
+  {
+    # SIGPIPE received when writing to syslog -- close and reopen
+    # the log handle, then try again.
+    closelog();
+    openlog_for_spamd();
+    syslog( 'debug', "%s", "syslog reopened" );
+    syslog( 'info', "%s", $msg );
+
+    # now report what happend
+    $msg = "SIGPIPE received, reopening log socket";
+    warn "logmsg: $msg\n" if $opt{'debug'};
+    syslog( 'warning', "%s", $msg );
+
+    # if we've received multiple sigpipes, logging is probably
+    # still broken.
+    if ( $main::SIGPIPE_RECEIVED > 1 ) {
+      warn "logging failure: multiple SIGPIPEs received\n";
+    }
+
+    $main::SIGPIPE_RECEIVED = 0;
+    return 1;
+  }
+
+  return 0;     # didn't have a SIGPIPE
 }
 
 sub openlog_for_spamd {
@@ -1744,7 +1767,10 @@
   $SIG{CHLD} = \&child_handler;    # reset as necessary
   my $pid = wait;                  # reap the child
   delete $children{$pid};          # remove the child out of the pool
-  logmsg("server hit by SIG$sig, pid $pid");
+
+  unless ($main::INHIBIT_LOGGING_IN_SIGCHLD_HANDLER) {
+    logmsg("server hit by SIG$sig, pid $pid");
+  }
 }
 
 sub restart_handler {