| Index: third_party/buildbot_7_12/buildbot/test/mail/svn-commit.2
|
| diff --git a/third_party/buildbot_7_12/buildbot/test/mail/svn-commit.2 b/third_party/buildbot_7_12/buildbot/test/mail/svn-commit.2
|
| deleted file mode 100644
|
| index eeef001ce5271ac3e7dd8ebdbd549a8e27e556c5..0000000000000000000000000000000000000000
|
| --- a/third_party/buildbot_7_12/buildbot/test/mail/svn-commit.2
|
| +++ /dev/null
|
| @@ -1,1218 +0,0 @@
|
| -X-Original-To: jm@jmason.org
|
| -Delivered-To: jm@dogma.boxhost.net
|
| -Received: from localhost [127.0.0.1]
|
| - by localhost with IMAP (fetchmail-6.2.5)
|
| - for jm@localhost (single-drop); Thu, 09 Mar 2006 21:44:57 +0000 (GMT)
|
| -Received: from minotaur.apache.org (minotaur.apache.org [209.237.227.194])
|
| - by dogma.boxhost.net (Postfix) with SMTP id 0D3463105BF
|
| - for <jm@jmason.org>; Thu, 9 Mar 2006 19:52:50 +0000 (GMT)
|
| -Received: (qmail 30661 invoked by uid 1833); 9 Mar 2006 19:52:44 -0000
|
| -Delivered-To: jm@locus.apache.org
|
| -Received: (qmail 30451 invoked from network); 9 Mar 2006 19:52:38 -0000
|
| -Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199)
|
| - by minotaur.apache.org with SMTP; 9 Mar 2006 19:52:38 -0000
|
| -Received: (qmail 97860 invoked by uid 500); 9 Mar 2006 19:52:29 -0000
|
| -Delivered-To: apmail-jm@apache.org
|
| -Received: (qmail 97837 invoked by uid 500); 9 Mar 2006 19:52:28 -0000
|
| -Mailing-List: contact commits-help@spamassassin.apache.org; run by ezmlm
|
| -Precedence: bulk
|
| -list-help: <mailto:commits-help@spamassassin.apache.org>
|
| -list-unsubscribe: <mailto:commits-unsubscribe@spamassassin.apache.org>
|
| -List-Post: <mailto:commits@spamassassin.apache.org>
|
| -Reply-To: "SpamAssassin Dev" <dev@spamassassin.apache.org>
|
| -List-Id: <commits.spamassassin.apache.org>
|
| -Delivered-To: mailing list commits@spamassassin.apache.org
|
| -Received: (qmail 97826 invoked by uid 99); 9 Mar 2006 19:52:28 -0000
|
| -Received: from asf.osuosl.org (HELO asf.osuosl.org) (140.211.166.49)
|
| - by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 09 Mar 2006 11:52:28 -0800
|
| -X-ASF-Spam-Status: No, hits=-9.4 required=10.0
|
| - tests=ALL_TRUSTED,NO_REAL_NAME
|
| -Received: from [209.237.227.194] (HELO minotaur.apache.org) (209.237.227.194)
|
| - by apache.org (qpsmtpd/0.29) with SMTP; Thu, 09 Mar 2006 11:52:26 -0800
|
| -Received: (qmail 29644 invoked by uid 65534); 9 Mar 2006 19:52:06 -0000
|
| -Message-ID: <20060309195206.29643.qmail@minotaur.apache.org>
|
| -Content-Type: text/plain; charset="utf-8"
|
| -MIME-Version: 1.0
|
| -Content-Transfer-Encoding: 7bit
|
| -Subject: svn commit: r384590 - in /spamassassin/branches/3.1: ./
|
| - lib/Mail/SpamAssassin/ lib/Mail/SpamAssassin/Plugin/ spamd/
|
| -Date: Thu, 09 Mar 2006 19:52:02 -0000
|
| -To: commits@spamassassin.apache.org
|
| -From: sidney@apache.org
|
| -X-Mailer: svnmailer-1.0.7
|
| -X-Virus-Checked: Checked by ClamAV on apache.org
|
| -Status: O
|
| -X-UID: 60795
|
| -X-Keywords:
|
| -
|
| -Author: sidney
|
| -Date: Thu Mar 9 11:51:59 2006
|
| -New Revision: 384590
|
| -
|
| -URL: http://svn.apache.org/viewcvs?rev=384590&view=rev
|
| -Log:
|
| -Bug 4696: consolidated fixes for timeout bugs
|
| -
|
| -Added:
|
| - spamassassin/branches/3.1/lib/Mail/SpamAssassin/Timeout.pm
|
| -Modified:
|
| - spamassassin/branches/3.1/MANIFEST
|
| - spamassassin/branches/3.1/lib/Mail/SpamAssassin/Logger.pm
|
| - spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/DCC.pm
|
| - spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/DomainKeys.pm
|
| - spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/Pyzor.pm
|
| - spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/Razor2.pm
|
| - spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/SPF.pm
|
| - spamassassin/branches/3.1/lib/Mail/SpamAssassin/SpamdForkScaling.pm
|
| - spamassassin/branches/3.1/spamd/spamd.raw
|
| -
|
| -Modified: spamassassin/branches/3.1/MANIFEST
|
| -URL: http://svn.apache.org/viewcvs/spamassassin/branches/3.1/MANIFEST?rev=384590&r1=384589&r2=384590&view=diff
|
| -==============================================================================
|
| ---- spamassassin/branches/3.1/MANIFEST (original)
|
| -+++ spamassassin/branches/3.1/MANIFEST Thu Mar 9 11:51:59 2006
|
| -@@ -89,6 +89,7 @@
|
| - lib/Mail/SpamAssassin/SQLBasedAddrList.pm
|
| - lib/Mail/SpamAssassin/SpamdForkScaling.pm
|
| - lib/Mail/SpamAssassin/SubProcBackChannel.pm
|
| -+lib/Mail/SpamAssassin/Timeout.pm
|
| - lib/Mail/SpamAssassin/Util.pm
|
| - lib/Mail/SpamAssassin/Util/DependencyInfo.pm
|
| - lib/Mail/SpamAssassin/Util/Progress.pm
|
| -
|
| -Modified: spamassassin/branches/3.1/lib/Mail/SpamAssassin/Logger.pm
|
| -URL: http://svn.apache.org/viewcvs/spamassassin/branches/3.1/lib/Mail/SpamAssassin/Logger.pm?rev=384590&r1=384589&r2=384590&view=diff
|
| -==============================================================================
|
| ---- spamassassin/branches/3.1/lib/Mail/SpamAssassin/Logger.pm (original)
|
| -+++ spamassassin/branches/3.1/lib/Mail/SpamAssassin/Logger.pm Thu Mar 9 11:51:59 2006
|
| -@@ -142,7 +142,7 @@
|
| -
|
| - if ($level eq "error") {
|
| - # don't log alarm timeouts or broken pipes of various plugins' network checks
|
| -- return if ($message[0] =~ /__(?:alarm|brokenpipe)__ignore__/);
|
| -+ return if ($message[0] =~ /__ignore__/);
|
| -
|
| - # dos: we can safely ignore any die's that we eval'd in our own modules so
|
| - # don't log them -- this is caller 0, the use'ing package is 1, the eval is 2
|
| -
|
| -Modified: spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/DCC.pm
|
| -URL: http://svn.apache.org/viewcvs/spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/DCC.pm?rev=384590&r1=384589&r2=384590&view=diff
|
| -==============================================================================
|
| ---- spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/DCC.pm (original)
|
| -+++ spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/DCC.pm Thu Mar 9 11:51:59 2006
|
| -@@ -44,6 +44,7 @@
|
| -
|
| - use Mail::SpamAssassin::Plugin;
|
| - use Mail::SpamAssassin::Logger;
|
| -+use Mail::SpamAssassin::Timeout;
|
| - use IO::Socket;
|
| - use strict;
|
| - use warnings;
|
| -@@ -375,15 +376,10 @@
|
| -
|
| - $permsgstatus->enter_helper_run_mode();
|
| -
|
| -- my $oldalarm = 0;
|
| -+ my $timer = Mail::SpamAssassin::Timeout->new({ secs => $timeout });
|
| -+ my $err = $timer->run_and_catch(sub {
|
| -
|
| -- eval {
|
| -- # safe to use $SIG{ALRM} here instead of Util::trap_sigalrm_fully(),
|
| -- # since there are no killer regexp hang dangers here
|
| -- local $SIG{ALRM} = sub { die "__alarm__ignore__\n" };
|
| -- local $SIG{__DIE__}; # bug 4631
|
| --
|
| -- $oldalarm = alarm $timeout;
|
| -+ local $SIG{PIPE} = sub { die "__brokenpipe__ignore__\n" };
|
| -
|
| - my $sock = IO::Socket::UNIX->new(Type => SOCK_STREAM,
|
| - Peer => $sockpath) || dbg("dcc: failed to open socket") && die;
|
| -@@ -419,28 +415,20 @@
|
| - }
|
| -
|
| - dbg("dcc: dccifd got response: $response");
|
| -+
|
| -+ });
|
| -
|
| -- if (defined $oldalarm) {
|
| -- alarm $oldalarm; $oldalarm = undef;
|
| -- }
|
| -- };
|
| -+ $permsgstatus->leave_helper_run_mode();
|
| -
|
| -- my $err = $@;
|
| -- if (defined $oldalarm) {
|
| -- alarm $oldalarm; $oldalarm = undef;
|
| -+ if ($timer->timed_out()) {
|
| -+ dbg("dcc: dccifd check timed out after $timeout secs.");
|
| -+ return 0;
|
| - }
|
| -- $permsgstatus->leave_helper_run_mode();
|
| -
|
| - if ($err) {
|
| - chomp $err;
|
| -- $response = undef;
|
| -- if ($err eq "__alarm__ignore__") {
|
| -- dbg("dcc: dccifd check timed out after $timeout secs.");
|
| -- return 0;
|
| -- } else {
|
| -- warn("dcc: dccifd -> check skipped: $! $err");
|
| -- return 0;
|
| -- }
|
| -+ warn("dcc: dccifd -> check skipped: $! $err");
|
| -+ return 0;
|
| - }
|
| -
|
| - if (!defined $response || $response !~ /^X-DCC/) {
|
| -@@ -494,17 +482,12 @@
|
| -
|
| - # use a temp file here -- open2() is unreliable, buffering-wise, under spamd
|
| - my $tmpf = $permsgstatus->create_fulltext_tmpfile($fulltext);
|
| -- my $oldalarm = 0;
|
| --
|
| - my $pid;
|
| -- eval {
|
| -- # safe to use $SIG{ALRM} here instead of Util::trap_sigalrm_fully(),
|
| -- # since there are no killer regexp hang dangers here
|
| -- local $SIG{ALRM} = sub { die "__alarm__ignore__\n" };
|
| -- local $SIG{PIPE} = sub { die "__brokenpipe__ignore__\n" };
|
| -- local $SIG{__DIE__}; # bug 4631
|
| -
|
| -- $oldalarm = alarm $timeout;
|
| -+ my $timer = Mail::SpamAssassin::Timeout->new({ secs => $timeout });
|
| -+ my $err = $timer->run_and_catch(sub {
|
| -+
|
| -+ local $SIG{PIPE} = sub { die "__brokenpipe__ignore__\n" };
|
| -
|
| - # note: not really tainted, this came from system configuration file
|
| - my $path = Mail::SpamAssassin::Util::untaint_file_path($self->{main}->{conf}->{dcc_path});
|
| -@@ -542,17 +525,7 @@
|
| -
|
| - dbg("dcc: got response: $response");
|
| -
|
| -- # note: this must be called BEFORE leave_helper_run_mode()
|
| -- # $self->cleanup_kids($pid);
|
| -- if (defined $oldalarm) {
|
| -- alarm $oldalarm; $oldalarm = undef;
|
| -- }
|
| -- };
|
| --
|
| -- my $err = $@;
|
| -- if (defined $oldalarm) {
|
| -- alarm $oldalarm; $oldalarm = undef;
|
| -- }
|
| -+ });
|
| -
|
| - if (defined(fileno(*DCC))) { # still open
|
| - if ($pid) {
|
| -@@ -564,11 +537,14 @@
|
| - }
|
| - $permsgstatus->leave_helper_run_mode();
|
| -
|
| -+ if ($timer->timed_out()) {
|
| -+ dbg("dcc: check timed out after $timeout seconds");
|
| -+ return 0;
|
| -+ }
|
| -+
|
| - if ($err) {
|
| - chomp $err;
|
| -- if ($err eq "__alarm__ignore__") {
|
| -- dbg("dcc: check timed out after $timeout seconds");
|
| -- } elsif ($err eq "__brokenpipe__ignore__") {
|
| -+ if ($err eq "__brokenpipe__ignore__") {
|
| - dbg("dcc: check failed: broken pipe");
|
| - } elsif ($err eq "no response") {
|
| - dbg("dcc: check failed: no response");
|
| -@@ -645,47 +621,37 @@
|
| - my ($self, $options, $tmpf) = @_;
|
| - my $timeout = $options->{report}->{conf}->{dcc_timeout};
|
| -
|
| -- $options->{report}->enter_helper_run_mode();
|
| -+ # note: not really tainted, this came from system configuration file
|
| -+ my $path = Mail::SpamAssassin::Util::untaint_file_path($options->{report}->{conf}->{dcc_path});
|
| -
|
| -- my $oldalarm = 0;
|
| -+ my $opts = $options->{report}->{conf}->{dcc_options} || '';
|
| -
|
| -- eval {
|
| -- local $SIG{ALRM} = sub { die "__alarm__ignore__\n" };
|
| -- local $SIG{PIPE} = sub { die "__brokenpipe__ignore__\n" };
|
| -- local $SIG{__DIE__}; # bug 4631
|
| -+ my $timer = Mail::SpamAssassin::Timeout->new({ secs => $timeout });
|
| -
|
| -- $oldalarm = alarm $timeout;
|
| --
|
| -- # note: not really tainted, this came from system configuration file
|
| -- my $path = Mail::SpamAssassin::Util::untaint_file_path($options->{report}->{conf}->{dcc_path});
|
| -+ $options->{report}->enter_helper_run_mode();
|
| -+ my $err = $timer->run_and_catch(sub {
|
| -
|
| -- my $opts = $options->{report}->{conf}->{dcc_options} || '';
|
| -+ local $SIG{PIPE} = sub { die "__brokenpipe__ignore__\n" };
|
| -
|
| - my $pid = Mail::SpamAssassin::Util::helper_app_pipe_open(*DCC,
|
| -- $tmpf, 1, $path, "-t", "many", split(' ', $opts));
|
| -+ $tmpf, 1, $path, "-t", "many", split(' ', $opts));
|
| - $pid or die "$!\n";
|
| -
|
| - my @ignored = <DCC>;
|
| - $options->{report}->close_pipe_fh(\*DCC);
|
| --
|
| - waitpid ($pid, 0);
|
| -- if (defined $oldalarm) {
|
| -- alarm $oldalarm; $oldalarm = undef;
|
| -- }
|
| -- };
|
| -+
|
| -+ });
|
| -+ $options->{report}->leave_helper_run_mode();
|
| -
|
| -- my $err = $@;
|
| -- if (defined $oldalarm) {
|
| -- alarm $oldalarm; $oldalarm = undef;
|
| -+ if ($timer->timed_out()) {
|
| -+ dbg("reporter: DCC report timed out after $timeout seconds");
|
| -+ return 0;
|
| - }
|
| -
|
| -- $options->{report}->leave_helper_run_mode();
|
| --
|
| - if ($err) {
|
| - chomp $err;
|
| -- if ($err eq "__alarm__ignore__") {
|
| -- dbg("reporter: DCC report timed out after $timeout seconds");
|
| -- } elsif ($err eq "__brokenpipe__ignore__") {
|
| -+ if ($err eq "__brokenpipe__ignore__") {
|
| - dbg("reporter: DCC report failed: broken pipe");
|
| - } else {
|
| - warn("reporter: DCC report failed: $err\n");
|
| -
|
| -Modified: spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/DomainKeys.pm
|
| -URL: http://svn.apache.org/viewcvs/spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/DomainKeys.pm?rev=384590&r1=384589&r2=384590&view=diff
|
| -==============================================================================
|
| ---- spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/DomainKeys.pm (original)
|
| -+++ spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/DomainKeys.pm Thu Mar 9 11:51:59 2006
|
| -@@ -34,6 +34,8 @@
|
| -
|
| - use Mail::SpamAssassin::Plugin;
|
| - use Mail::SpamAssassin::Logger;
|
| -+use Mail::SpamAssassin::Timeout;
|
| -+
|
| - use strict;
|
| - use warnings;
|
| - use bytes;
|
| -@@ -165,30 +167,22 @@
|
| - }
|
| -
|
| - my $timeout = $scan->{conf}->{domainkeys_timeout};
|
| -- my $oldalarm = 0;
|
| -
|
| -- eval {
|
| -- local $SIG{ALRM} = sub { die "__alarm__ignore__\n" };
|
| -- local $SIG{__DIE__}; # bug 4631
|
| -- $oldalarm = alarm($timeout);
|
| -+ my $timer = Mail::SpamAssassin::Timeout->new({ secs => $timeout });
|
| -+ my $err = $timer->run_and_catch(sub {
|
| -+
|
| - $self->_dk_lookup_trapped($scan, $message, $domain);
|
| -- if (defined $oldalarm) {
|
| -- alarm $oldalarm; $oldalarm = undef;
|
| -- }
|
| -- };
|
| --
|
| -- my $err = $@;
|
| -- if (defined $oldalarm) {
|
| -- alarm $oldalarm; $oldalarm = undef;
|
| -+
|
| -+ });
|
| -+
|
| -+ if ($timer->timed_out()) {
|
| -+ dbg("dk: lookup timed out after $timeout seconds");
|
| -+ return 0;
|
| - }
|
| -
|
| - if ($err) {
|
| - chomp $err;
|
| -- if ($err eq "__alarm__ignore__") {
|
| -- dbg("dk: lookup timed out after $timeout seconds");
|
| -- } else {
|
| -- warn("dk: lookup failed: $err\n");
|
| -- }
|
| -+ warn("dk: lookup failed: $err\n");
|
| - return 0;
|
| - }
|
| -
|
| -
|
| -Modified: spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/Pyzor.pm
|
| -URL: http://svn.apache.org/viewcvs/spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/Pyzor.pm?rev=384590&r1=384589&r2=384590&view=diff
|
| -==============================================================================
|
| ---- spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/Pyzor.pm (original)
|
| -+++ spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/Pyzor.pm Thu Mar 9 11:51:59 2006
|
| -@@ -35,6 +35,7 @@
|
| -
|
| - use Mail::SpamAssassin::Plugin;
|
| - use Mail::SpamAssassin::Logger;
|
| -+use Mail::SpamAssassin::Timeout;
|
| - use strict;
|
| - use warnings;
|
| - use bytes;
|
| -@@ -229,27 +230,22 @@
|
| -
|
| - $pyzor_count = 0;
|
| - $pyzor_whitelisted = 0;
|
| --
|
| -- $permsgstatus->enter_helper_run_mode();
|
| -+ my $pid;
|
| -
|
| - # use a temp file here -- open2() is unreliable, buffering-wise, under spamd
|
| - my $tmpf = $permsgstatus->create_fulltext_tmpfile($fulltext);
|
| -- my $oldalarm = 0;
|
| -
|
| -- my $pid;
|
| -- eval {
|
| -- # safe to use $SIG{ALRM} here instead of Util::trap_sigalrm_fully(),
|
| -- # since there are no killer regexp hang dangers here
|
| -- local $SIG{ALRM} = sub { die "__alarm__ignore__\n" };
|
| -- local $SIG{PIPE} = sub { die "__brokenpipe__ignore__\n" };
|
| -- local $SIG{__DIE__}; # bug 4631
|
| -+ # note: not really tainted, this came from system configuration file
|
| -+ my $path = Mail::SpamAssassin::Util::untaint_file_path($self->{main}->{conf}->{pyzor_path});
|
| -+
|
| -+ my $opts = $self->{main}->{conf}->{pyzor_options} || '';
|
| -
|
| -- $oldalarm = alarm $timeout;
|
| -+ $permsgstatus->enter_helper_run_mode();
|
| -
|
| -- # note: not really tainted, this came from system configuration file
|
| -- my $path = Mail::SpamAssassin::Util::untaint_file_path($self->{main}->{conf}->{pyzor_path});
|
| -+ my $timer = Mail::SpamAssassin::Timeout->new({ secs => $timeout });
|
| -+ my $err = $timer->run_and_catch(sub {
|
| -
|
| -- my $opts = $self->{main}->{conf}->{pyzor_options} || '';
|
| -+ local $SIG{PIPE} = sub { die "__brokenpipe__ignore__\n" };
|
| -
|
| - dbg("pyzor: opening pipe: " . join(' ', $path, $opts, "check", "< $tmpf"));
|
| -
|
| -@@ -273,21 +269,7 @@
|
| - die("internal error\n");
|
| - }
|
| -
|
| -- # note: this must be called BEFORE leave_helper_run_mode()
|
| -- # $self->cleanup_kids($pid);
|
| --
|
| -- # attempt to call this inside the eval, as leaving this scope is
|
| -- # a slow operation and timing *that* out is pointless
|
| -- if (defined $oldalarm) {
|
| -- alarm $oldalarm; $oldalarm = undef;
|
| -- }
|
| -- };
|
| --
|
| -- # clear the alarm before doing lots of time-consuming hard work
|
| -- my $err = $@;
|
| -- if (defined $oldalarm) {
|
| -- alarm $oldalarm; $oldalarm = undef;
|
| -- }
|
| -+ });
|
| -
|
| - if (defined(fileno(*PYZOR))) { # still open
|
| - if ($pid) {
|
| -@@ -299,11 +281,14 @@
|
| - }
|
| - $permsgstatus->leave_helper_run_mode();
|
| -
|
| -+ if ($timer->timed_out()) {
|
| -+ dbg("pyzor: check timed out after $timeout seconds");
|
| -+ return 0;
|
| -+ }
|
| -+
|
| - if ($err) {
|
| - chomp $err;
|
| -- if ($err eq "__alarm__ignore__") {
|
| -- dbg("pyzor: check timed out after $timeout seconds");
|
| -- } elsif ($err eq "__brokenpipe__ignore__") {
|
| -+ if ($err eq "__brokenpipe__ignore__") {
|
| - dbg("pyzor: check failed: broken pipe");
|
| - } elsif ($err eq "no response") {
|
| - dbg("pyzor: check failed: no response");
|
| -@@ -364,23 +349,19 @@
|
| -
|
| - sub pyzor_report {
|
| - my ($self, $options, $tmpf) = @_;
|
| -+
|
| -+ # note: not really tainted, this came from system configuration file
|
| -+ my $path = Mail::SpamAssassin::Util::untaint_file_path($options->{report}->{conf}->{pyzor_path});
|
| -+
|
| -+ my $opts = $options->{report}->{conf}->{pyzor_options} || '';
|
| - my $timeout = $self->{main}->{conf}->{pyzor_timeout};
|
| -
|
| - $options->{report}->enter_helper_run_mode();
|
| -
|
| -- my $oldalarm = 0;
|
| -+ my $timer = Mail::SpamAssassin::Timeout->new({ secs => $timeout });
|
| -+ my $err = $timer->run_and_catch(sub {
|
| -
|
| -- eval {
|
| -- local $SIG{ALRM} = sub { die "__alarm__ignore__\n" };
|
| - local $SIG{PIPE} = sub { die "__brokenpipe__ignore__\n" };
|
| -- local $SIG{__DIE__}; # bug 4631
|
| --
|
| -- $oldalarm = alarm $timeout;
|
| --
|
| -- # note: not really tainted, this came from system configuration file
|
| -- my $path = Mail::SpamAssassin::Util::untaint_file_path($options->{report}->{conf}->{pyzor_path});
|
| --
|
| -- my $opts = $options->{report}->{conf}->{pyzor_options} || '';
|
| -
|
| - dbg("pyzor: opening pipe: " . join(' ', $path, $opts, "report", "< $tmpf"));
|
| -
|
| -@@ -391,23 +372,19 @@
|
| - my @ignored = <PYZOR>;
|
| - $options->{report}->close_pipe_fh(\*PYZOR);
|
| -
|
| -- if (defined $oldalarm) {
|
| -- alarm $oldalarm; $oldalarm = undef;
|
| -- }
|
| - waitpid ($pid, 0);
|
| -- };
|
| -+ });
|
| -
|
| -- my $err = $@;
|
| -- if (defined $oldalarm) {
|
| -- alarm $oldalarm; $oldalarm = undef;
|
| -- }
|
| - $options->{report}->leave_helper_run_mode();
|
| -
|
| -+ if ($timer->timed_out()) {
|
| -+ dbg("reporter: pyzor report timed out after $timeout seconds");
|
| -+ return 0;
|
| -+ }
|
| -+
|
| - if ($err) {
|
| - chomp $err;
|
| -- if ($err eq '__alarm__ignore__') {
|
| -- dbg("reporter: pyzor report timed out after $timeout seconds");
|
| -- } elsif ($err eq '__brokenpipe__ignore__') {
|
| -+ if ($err eq '__brokenpipe__ignore__') {
|
| - dbg("reporter: pyzor report failed: broken pipe");
|
| - } else {
|
| - warn("reporter: pyzor report failed: $err\n");
|
| -
|
| -Modified: spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/Razor2.pm
|
| -URL: http://svn.apache.org/viewcvs/spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/Razor2.pm?rev=384590&r1=384589&r2=384590&view=diff
|
| -==============================================================================
|
| ---- spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/Razor2.pm (original)
|
| -+++ spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/Razor2.pm Thu Mar 9 11:51:59 2006
|
| -@@ -143,14 +143,11 @@
|
| - }
|
| -
|
| - Mail::SpamAssassin::PerMsgStatus::enter_helper_run_mode($self);
|
| -- my $oldalarm = 0;
|
| -
|
| -- eval {
|
| -- local ($^W) = 0; # argh, warnings in Razor
|
| -+ my $timer = Mail::SpamAssassin::Timeout->new({ secs => $timeout });
|
| -+ my $err = $timer->run_and_catch(sub {
|
| -
|
| -- local $SIG{ALRM} = sub { die "__alarm__ignore__\n" };
|
| -- local $SIG{__DIE__}; # bug 4631
|
| -- $oldalarm = alarm $timeout;
|
| -+ local ($^W) = 0; # argh, warnings in Razor
|
| -
|
| - # everything's in the module!
|
| - my $rc = Razor2::Client::Agent->new("razor-$type");
|
| -@@ -184,7 +181,7 @@
|
| - # let's reset the alarm since get_server_info() calls
|
| - # nextserver() which calls discover() which very likely will
|
| - # reset the alarm for us ... how polite. :(
|
| -- alarm $timeout;
|
| -+ $timer->reset();
|
| -
|
| - # no facility prefix on this die
|
| - my $sigs = $rc->compute_sigs($objects)
|
| -@@ -219,100 +216,96 @@
|
| - my $error = $rc->errprefix("$debug: spamassassin") || "$debug: razor2 had unknown error during disconnect";
|
| - die $error;
|
| - }
|
| -+ }
|
| -
|
| -- # if we got here, we're done doing remote stuff, abort the alert
|
| -- if (defined $oldalarm) {
|
| -- alarm $oldalarm; $oldalarm = undef;
|
| -- }
|
| --
|
| -- # Razor 2.14 says that if we get here, we did ok.
|
| -- $return = 1;
|
| -+ # Razor 2.14 says that if we get here, we did ok.
|
| -+ $return = 1;
|
| -
|
| -- # figure out if we have a log file we need to close...
|
| -- if (ref($rc->{logref}) && exists $rc->{logref}->{fd}) {
|
| -- # the fd can be stdout or stderr, so we need to find out if it is
|
| -- # so we don't close them by accident. Note: we can't just
|
| -- # undef the fd here (like the IO::Handle manpage says we can)
|
| -- # because it won't actually close, unfortunately. :(
|
| -- my $untie = 1;
|
| -- foreach my $log (*STDOUT{IO}, *STDERR{IO}) {
|
| -- if ($log == $rc->{logref}->{fd}) {
|
| -- $untie = 0;
|
| -- last;
|
| -- }
|
| -- }
|
| -- close $rc->{logref}->{fd} if ($untie);
|
| -- }
|
| --
|
| -- if ($type eq 'check') {
|
| -- # so $objects->[0] is the first (only) message, and ->{spam} is a general yes/no
|
| -- push(@results, { result => $objects->[0]->{spam} });
|
| -+ # figure out if we have a log file we need to close...
|
| -+ if (ref($rc->{logref}) && exists $rc->{logref}->{fd}) {
|
| -+ # the fd can be stdout or stderr, so we need to find out if it is
|
| -+ # so we don't close them by accident. Note: we can't just
|
| -+ # undef the fd here (like the IO::Handle manpage says we can)
|
| -+ # because it won't actually close, unfortunately. :(
|
| -+ my $untie = 1;
|
| -+ foreach my $log (*STDOUT{IO}, *STDERR{IO}) {
|
| -+ if ($log == $rc->{logref}->{fd}) {
|
| -+ $untie = 0;
|
| -+ last;
|
| -+ }
|
| -+ }
|
| -+ close $rc->{logref}->{fd} if ($untie);
|
| -+ }
|
| -
|
| -- # great for debugging, but leave this off!
|
| -- #use Data::Dumper;
|
| -- #print Dumper($objects),"\n";
|
| --
|
| -- # ->{p} is for each part of the message
|
| -- # so go through each part, taking the highest cf we find
|
| -- # of any part that isn't contested (ct). This helps avoid false
|
| -- # positives. equals logic_method 4.
|
| -- #
|
| -- # razor-agents < 2.14 have a different object format, so we now support both.
|
| -- # $objects->[0]->{resp} vs $objects->[0]->{p}->[part #]->{resp}
|
| -- my $part = 0;
|
| -- my $arrayref = $objects->[0]->{p} || $objects;
|
| -- if (defined $arrayref) {
|
| -- foreach my $cf (@{$arrayref}) {
|
| -- if (exists $cf->{resp}) {
|
| -- for (my $response=0; $response<@{$cf->{resp}}; $response++) {
|
| -- my $tmp = $cf->{resp}->[$response];
|
| -- my $tmpcf = $tmp->{cf}; # Part confidence
|
| -- my $tmpct = $tmp->{ct}; # Part contested?
|
| -- my $engine = $cf->{sent}->[$response]->{e};
|
| --
|
| -- # These should always be set, but just in case ...
|
| -- $tmpcf = 0 unless defined $tmpcf;
|
| -- $tmpct = 0 unless defined $tmpct;
|
| -- $engine = 0 unless defined $engine;
|
| --
|
| -- push(@results,
|
| -- { part => $part, engine => $engine, contested => $tmpct, confidence => $tmpcf });
|
| -- }
|
| -- }
|
| -- else {
|
| -- push(@results, { part => $part, noresponse => 1 });
|
| -- }
|
| -- $part++;
|
| -- }
|
| -- }
|
| -- else {
|
| -- # If we have some new $objects format that isn't close to
|
| -- # the current razor-agents 2.x version, we won't FP but we
|
| -- # should alert in debug.
|
| -- dbg("$debug: it looks like the internal Razor object has changed format!");
|
| -- }
|
| -- }
|
| -+ if ($type eq 'check') {
|
| -+ # so $objects->[0] is the first (only) message, and ->{spam} is a general yes/no
|
| -+ push(@results, { result => $objects->[0]->{spam} });
|
| -+
|
| -+ # great for debugging, but leave this off!
|
| -+ #use Data::Dumper;
|
| -+ #print Dumper($objects),"\n";
|
| -+
|
| -+ # ->{p} is for each part of the message
|
| -+ # so go through each part, taking the highest cf we find
|
| -+ # of any part that isn't contested (ct). This helps avoid false
|
| -+ # positives. equals logic_method 4.
|
| -+ #
|
| -+ # razor-agents < 2.14 have a different object format, so we now support both.
|
| -+ # $objects->[0]->{resp} vs $objects->[0]->{p}->[part #]->{resp}
|
| -+ my $part = 0;
|
| -+ my $arrayref = $objects->[0]->{p} || $objects;
|
| -+ if (defined $arrayref) {
|
| -+ foreach my $cf (@{$arrayref}) {
|
| -+ if (exists $cf->{resp}) {
|
| -+ for (my $response=0; $response<@{$cf->{resp}}; $response++) {
|
| -+ my $tmp = $cf->{resp}->[$response];
|
| -+ my $tmpcf = $tmp->{cf}; # Part confidence
|
| -+ my $tmpct = $tmp->{ct}; # Part contested?
|
| -+ my $engine = $cf->{sent}->[$response]->{e};
|
| -+
|
| -+ # These should always be set, but just in case ...
|
| -+ $tmpcf = 0 unless defined $tmpcf;
|
| -+ $tmpct = 0 unless defined $tmpct;
|
| -+ $engine = 0 unless defined $engine;
|
| -+
|
| -+ push(@results,
|
| -+ { part => $part, engine => $engine, contested => $tmpct, confidence => $tmpcf });
|
| -+ }
|
| -+ }
|
| -+ else {
|
| -+ push(@results, { part => $part, noresponse => 1 });
|
| -+ }
|
| -+ $part++;
|
| -+ }
|
| -+ }
|
| -+ else {
|
| -+ # If we have some new $objects format that isn't close to
|
| -+ # the current razor-agents 2.x version, we won't FP but we
|
| -+ # should alert in debug.
|
| -+ dbg("$debug: it looks like the internal Razor object has changed format!");
|
| -+ }
|
| - }
|
| - }
|
| - else {
|
| - warn "$debug: undefined Razor2::Client::Agent\n";
|
| - }
|
| -
|
| -- if (defined $oldalarm) {
|
| -- alarm $oldalarm; $oldalarm = undef;
|
| -- }
|
| -- };
|
| -+ });
|
| -+
|
| -+ # OK, that's enough Razor stuff. now, reset all that global
|
| -+ # state it futzes with :(
|
| -+ # work around serious brain damage in Razor2 (constant seed)
|
| -+ srand;
|
| -
|
| -- my $err = $@;
|
| -- if (defined $oldalarm) {
|
| -- alarm $oldalarm; $oldalarm = undef;
|
| -+ Mail::SpamAssassin::PerMsgStatus::leave_helper_run_mode($self);
|
| -+
|
| -+ if ($timer->timed_out()) {
|
| -+ dbg("$debug: razor2 $type timed out after $timeout seconds");
|
| - }
|
| -
|
| - if ($err) {
|
| - chomp $err;
|
| -- if ($err eq "__alarm__ignore__") {
|
| -- dbg("$debug: razor2 $type timed out after $timeout seconds");
|
| -- } elsif ($err =~ /(?:could not connect|network is unreachable)/) {
|
| -+ if ($err =~ /(?:could not connect|network is unreachable)/) {
|
| - # make this a dbg(); SpamAssassin will still continue,
|
| - # but without Razor checking. otherwise there may be
|
| - # DSNs and errors in syslog etc., yuck
|
| -@@ -323,11 +316,6 @@
|
| - warn("$debug: razor2 $type failed: $! $err");
|
| - }
|
| - }
|
| --
|
| -- # work around serious brain damage in Razor2 (constant seed)
|
| -- srand;
|
| --
|
| -- Mail::SpamAssassin::PerMsgStatus::leave_helper_run_mode($self);
|
| -
|
| - # razor also debugs to stdout. argh. fix it to stderr...
|
| - if (would_log('dbg', $debug)) {
|
| -
|
| -Modified: spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/SPF.pm
|
| -URL: http://svn.apache.org/viewcvs/spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/SPF.pm?rev=384590&r1=384589&r2=384590&view=diff
|
| -==============================================================================
|
| ---- spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/SPF.pm (original)
|
| -+++ spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/SPF.pm Thu Mar 9 11:51:59 2006
|
| -@@ -34,6 +34,7 @@
|
| -
|
| - use Mail::SpamAssassin::Plugin;
|
| - use Mail::SpamAssassin::Logger;
|
| -+use Mail::SpamAssassin::Timeout;
|
| - use strict;
|
| - use warnings;
|
| - use bytes;
|
| -@@ -300,30 +301,17 @@
|
| -
|
| - my ($result, $comment);
|
| - my $timeout = $scanner->{conf}->{spf_timeout};
|
| -- my $oldalarm = 0;
|
| -
|
| -- eval {
|
| -- local $SIG{ALRM} = sub { die "__alarm__ignore__\n" };
|
| -- local $SIG{__DIE__}; # bug 4631
|
| -- $oldalarm = alarm($timeout);
|
| -+ my $timer = Mail::SpamAssassin::Timeout->new({ secs => $timeout });
|
| -+ my $err = $timer->run_and_catch(sub {
|
| -+
|
| - ($result, $comment) = $query->result();
|
| -- if (defined $oldalarm) {
|
| -- alarm $oldalarm; $oldalarm = undef;
|
| -- }
|
| -- };
|
| -
|
| -- my $err = $@;
|
| -- if (defined $oldalarm) {
|
| -- alarm $oldalarm; $oldalarm = undef;
|
| -- }
|
| -+ });
|
| -
|
| - if ($err) {
|
| - chomp $err;
|
| -- if ($err eq "__alarm__ignore__") {
|
| -- dbg("spf: lookup timed out after $timeout seconds");
|
| -- } else {
|
| -- warn("spf: lookup failed: $err\n");
|
| -- }
|
| -+ warn("spf: lookup failed: $err\n");
|
| - return 0;
|
| - }
|
| -
|
| -
|
| -Modified: spamassassin/branches/3.1/lib/Mail/SpamAssassin/SpamdForkScaling.pm
|
| -URL: http://svn.apache.org/viewcvs/spamassassin/branches/3.1/lib/Mail/SpamAssassin/SpamdForkScaling.pm?rev=384590&r1=384589&r2=384590&view=diff
|
| -==============================================================================
|
| ---- spamassassin/branches/3.1/lib/Mail/SpamAssassin/SpamdForkScaling.pm (original)
|
| -+++ spamassassin/branches/3.1/lib/Mail/SpamAssassin/SpamdForkScaling.pm Thu Mar 9 11:51:59 2006
|
| -@@ -25,6 +25,7 @@
|
| -
|
| - use Mail::SpamAssassin::Util;
|
| - use Mail::SpamAssassin::Logger;
|
| -+use Mail::SpamAssassin::Timeout;
|
| -
|
| - use vars qw {
|
| - @PFSTATE_VARS %EXPORT_TAGS @EXPORT_OK
|
| -@@ -109,6 +110,9 @@
|
| -
|
| - delete $self->{kids}->{$pid};
|
| -
|
| -+ # note this for the select()-caller's benefit
|
| -+ $self->{child_just_exited} = 1;
|
| -+
|
| - # remove the child from the backchannel list, too
|
| - $self->{backchannel}->delete_socket_for_child($pid);
|
| -
|
| -@@ -188,24 +192,63 @@
|
| - vec($rin, $self->{server_fileno}, 1) = 0;
|
| - }
|
| -
|
| -- my ($rout, $eout, $nfound, $timeleft);
|
| -+ my ($rout, $eout, $nfound, $timeleft, $selerr);
|
| -+
|
| -+ # use alarm to back up select()'s built-in alarm, to debug Theo's bug.
|
| -+ # not that I can remember what Theo's bug was, but hey ;) A good
|
| -+ # 60 seconds extra on the alarm() should make that quite rare...
|
| -+
|
| -+ my $timer = Mail::SpamAssassin::Timeout->new({ secs => ($tout*2) + 60 });
|
| -
|
| -- # use alarm to back up select()'s built-in alarm, to debug theo's bug
|
| -- eval {
|
| -- Mail::SpamAssassin::Util::trap_sigalrm_fully(sub { die "tcp timeout"; });
|
| -- alarm ($tout*2) if ($tout);
|
| -+ $timer->run(sub {
|
| -+
|
| -+ $self->{child_just_exited} = 0;
|
| - ($nfound, $timeleft) = select($rout=$rin, undef, $eout=$rin, $tout);
|
| -- };
|
| -- alarm 0;
|
| -+ $selerr = $!;
|
| -
|
| -- if ($@) {
|
| -- warn "prefork: select timeout failed! recovering\n";
|
| -- sleep 1; # avoid overload
|
| -- return;
|
| -- }
|
| -+ });
|
| -+
|
| -+ # bug 4696: under load, the process can go for such a long time without
|
| -+ # being context-switched in, that when it does return the alarm() fires
|
| -+ # before the select() timeout does. Treat this as a select() timeout
|
| -+ if ($timer->timed_out) {
|
| -+ dbg("prefork: select timed out (via alarm)");
|
| -+ $nfound = 0;
|
| -+ $timeleft = 0;
|
| -+ }
|
| -+
|
| -+ # errors; handle undef *or* -1 returned. do this before "errors on
|
| -+ # the handle" below, since an error condition is signalled both via
|
| -+ # a -1 return and a $eout bit.
|
| -+ if (!defined $nfound || $nfound < 0)
|
| -+ {
|
| -+ if (exists &Errno::EINTR && $selerr == &Errno::EINTR)
|
| -+ {
|
| -+ # this happens if the process is signalled during the select(),
|
| -+ # for example if someone sends SIGHUP to reload the configuration.
|
| -+ # just return inmmediately
|
| -+ dbg("prefork: select returned err $selerr, probably signalled");
|
| -+ return;
|
| -+ }
|
| -+
|
| -+ # if a child exits during that select() call, it generates a spurious
|
| -+ # error, like this:
|
| -+ #
|
| -+ # Jan 29 12:53:17 dogma spamd[18518]: prefork: child states: BI
|
| -+ # Jan 29 12:53:17 dogma spamd[18518]: spamd: handled cleanup of child pid 13101 due to SIGCHLD
|
| -+ # Jan 29 12:53:17 dogma spamd[18518]: prefork: select returned -1! recovering:
|
| -+ #
|
| -+ # avoid by setting a boolean in the child_exited() callback and checking
|
| -+ # it here. log $! just in case, though.
|
| -+ if ($self->{child_just_exited} && $nfound == -1) {
|
| -+ dbg("prefork: select returned -1 due to child exiting, ignored ($selerr)");
|
| -+ return;
|
| -+ }
|
| -+
|
| -+ warn "prefork: select returned ".
|
| -+ (defined $nfound ? $nfound : "undef").
|
| -+ "! recovering: $selerr\n";
|
| -
|
| -- if (!defined $nfound) {
|
| -- warn "prefork: select returned undef! recovering\n";
|
| - sleep 1; # avoid overload
|
| - return;
|
| - }
|
| -@@ -213,7 +256,7 @@
|
| - # errors on the handle?
|
| - # return them immediately, they may be from a SIGHUP restart signal
|
| - if (vec ($eout, $self->{server_fileno}, 1)) {
|
| -- warn "prefork: select returned error on server filehandle: $!\n";
|
| -+ warn "prefork: select returned error on server filehandle: $selerr $!\n";
|
| - return;
|
| - }
|
| -
|
| -@@ -282,7 +325,7 @@
|
| -
|
| - my ($sock, $kid);
|
| - while (($kid, $sock) = each %{$self->{backchannel}->{kids}}) {
|
| -- $self->syswrite_with_retry($sock, PF_PING_ORDER) and next;
|
| -+ $self->syswrite_with_retry($sock, PF_PING_ORDER, $kid, 3) and next;
|
| -
|
| - warn "prefork: write of ping failed to $kid fd=".$sock->fileno.": ".$!;
|
| -
|
| -@@ -353,7 +396,7 @@
|
| - return $self->order_idle_child_to_accept();
|
| - }
|
| -
|
| -- if (!$self->syswrite_with_retry($sock, PF_ACCEPT_ORDER))
|
| -+ if (!$self->syswrite_with_retry($sock, PF_ACCEPT_ORDER, $kid))
|
| - {
|
| - # failure to write to the child; bad news. call it dead
|
| - warn "prefork: killing rogue child $kid, failed to write on fd ".$sock->fileno.": $!\n";
|
| -@@ -396,7 +439,7 @@
|
| - my ($self, $kid) = @_;
|
| - if ($self->{waiting_for_idle_child}) {
|
| - my $sock = $self->{backchannel}->get_socket_for_child($kid);
|
| -- $self->syswrite_with_retry($sock, PF_ACCEPT_ORDER)
|
| -+ $self->syswrite_with_retry($sock, PF_ACCEPT_ORDER, $kid)
|
| - or die "prefork: $kid claimed it was ready, but write failed on fd ".
|
| - $sock->fileno.": ".$!;
|
| - $self->{waiting_for_idle_child} = 0;
|
| -@@ -426,7 +469,7 @@
|
| - sub report_backchannel_socket {
|
| - my ($self, $str) = @_;
|
| - my $sock = $self->{backchannel}->get_parent_socket();
|
| -- $self->syswrite_with_retry($sock, $str)
|
| -+ $self->syswrite_with_retry($sock, $str, 'parent')
|
| - or write "syswrite() to parent failed: $!";
|
| - }
|
| -
|
| -@@ -537,12 +580,31 @@
|
| - }
|
| -
|
| - sub syswrite_with_retry {
|
| -- my ($self, $sock, $buf) = @_;
|
| -+ my ($self, $sock, $buf, $targetname, $numretries) = @_;
|
| -+ $numretries ||= 10; # default 10 retries
|
| -
|
| - my $written = 0;
|
| -+ my $try = 0;
|
| -
|
| - retry_write:
|
| -+
|
| -+ $try++;
|
| -+ if ($try > 1) {
|
| -+ warn "prefork: syswrite(".$sock->fileno.") to $targetname failed on try $try";
|
| -+ if ($try > $numretries) {
|
| -+ warn "prefork: giving up";
|
| -+ return undef;
|
| -+ }
|
| -+ else {
|
| -+ # give it 1 second to recover. we retry indefinitely.
|
| -+ my $rout = '';
|
| -+ vec($rout, $sock->fileno, 1) = 1;
|
| -+ select(undef, $rout, undef, 1);
|
| -+ }
|
| -+ }
|
| -+
|
| - my $nbytes = $sock->syswrite($buf);
|
| -+
|
| - if (!defined $nbytes) {
|
| - unless ((exists &Errno::EAGAIN && $! == &Errno::EAGAIN)
|
| - || (exists &Errno::EWOULDBLOCK && $! == &Errno::EWOULDBLOCK))
|
| -@@ -551,13 +613,7 @@
|
| - return undef;
|
| - }
|
| -
|
| -- warn "prefork: syswrite(".$sock->fileno.") failed, retrying...";
|
| --
|
| -- # give it 5 seconds to recover. we retry indefinitely.
|
| -- my $rout = '';
|
| -- vec($rout, $sock->fileno, 1) = 1;
|
| -- select(undef, $rout, undef, 5);
|
| --
|
| -+ warn "prefork: retrying syswrite(): $!";
|
| - goto retry_write;
|
| - }
|
| - else {
|
| -@@ -568,7 +624,8 @@
|
| - return $written; # it's complete, we can return
|
| - }
|
| - else {
|
| -- warn "prefork: partial write of $nbytes, towrite=".length($buf).
|
| -+ warn "prefork: partial write of $nbytes to ".
|
| -+ $targetname.", towrite=".length($buf).
|
| - " sofar=".$written." fd=".$sock->fileno.", recovering";
|
| - goto retry_write;
|
| - }
|
| -
|
| -Added: spamassassin/branches/3.1/lib/Mail/SpamAssassin/Timeout.pm
|
| -URL: http://svn.apache.org/viewcvs/spamassassin/branches/3.1/lib/Mail/SpamAssassin/Timeout.pm?rev=384590&view=auto
|
| -==============================================================================
|
| ---- spamassassin/branches/3.1/lib/Mail/SpamAssassin/Timeout.pm (added)
|
| -+++ spamassassin/branches/3.1/lib/Mail/SpamAssassin/Timeout.pm Thu Mar 9 11:51:59 2006
|
| -@@ -0,0 +1,215 @@
|
| -+# <@LICENSE>
|
| -+# Copyright 2004 Apache Software Foundation
|
| -+#
|
| -+# Licensed under the Apache License, Version 2.0 (the "License");
|
| -+# you may not use this file except in compliance with the License.
|
| -+# You may obtain a copy of the License at
|
| -+#
|
| -+# http://www.apache.org/licenses/LICENSE-2.0
|
| -+#
|
| -+# Unless required by applicable law or agreed to in writing, software
|
| -+# distributed under the License is distributed on an "AS IS" BASIS,
|
| -+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| -+# See the License for the specific language governing permissions and
|
| -+# limitations under the License.
|
| -+# </@LICENSE>
|
| -+
|
| -+=head1 NAME
|
| -+
|
| -+Mail::SpamAssassin::Timeout - safe, reliable timeouts in perl
|
| -+
|
| -+=head1 SYNOPSIS
|
| -+
|
| -+ # non-timeout code...
|
| -+
|
| -+ my $t = Mail::SpamAssassin::Timeout->new({ secs => 5 });
|
| -+
|
| -+ $t->run(sub {
|
| -+ # code to run with a 5-second timeout...
|
| -+ });
|
| -+
|
| -+ if ($t->timed_out()) {
|
| -+ # do something...
|
| -+ }
|
| -+
|
| -+ # more non-timeout code...
|
| -+
|
| -+=head1 DESCRIPTION
|
| -+
|
| -+This module provides a safe, reliable and clean API to provide
|
| -+C<alarm(2)>-based timeouts for perl code.
|
| -+
|
| -+Note that C<$SIG{ALRM}> is used to provide the timeout, so this will not
|
| -+interrupt out-of-control regular expression matches.
|
| -+
|
| -+Nested timeouts are supported.
|
| -+
|
| -+=head1 PUBLIC METHODS
|
| -+
|
| -+=over 4
|
| -+
|
| -+=cut
|
| -+
|
| -+package Mail::SpamAssassin::Timeout;
|
| -+
|
| -+use strict;
|
| -+use warnings;
|
| -+use bytes;
|
| -+
|
| -+use vars qw{
|
| -+ @ISA
|
| -+};
|
| -+
|
| -+@ISA = qw();
|
| -+
|
| -+###########################################################################
|
| -+
|
| -+=item my $t = Mail::SpamAssassin::Timeout->new({ ... options ... });
|
| -+
|
| -+Constructor. Options include:
|
| -+
|
| -+=over 4
|
| -+
|
| -+=item secs => $seconds
|
| -+
|
| -+timeout, in seconds. Optional; if not specified, no timeouts will be applied.
|
| -+
|
| -+=back
|
| -+
|
| -+=cut
|
| -+
|
| -+sub new {
|
| -+ my ($class, $opts) = @_;
|
| -+ $class = ref($class) || $class;
|
| -+ my %selfval = $opts ? %{$opts} : ();
|
| -+ my $self = \%selfval;
|
| -+
|
| -+ bless ($self, $class);
|
| -+ $self;
|
| -+}
|
| -+
|
| -+###########################################################################
|
| -+
|
| -+=item $t->run($coderef)
|
| -+
|
| -+Run a code reference within the currently-defined timeout.
|
| -+
|
| -+The timeout is as defined by the B<secs> parameter to the constructor.
|
| -+
|
| -+Returns whatever the subroutine returns, or C<undef> on timeout.
|
| -+If the timer times out, C<$t-<gt>timed_out()> will return C<1>.
|
| -+
|
| -+Time elapsed is not cumulative; multiple runs of C<run> will restart the
|
| -+timeout from scratch.
|
| -+
|
| -+=item $t->run_and_catch($coderef)
|
| -+
|
| -+Run a code reference, as per C<$t-<gt>run()>, but also catching any
|
| -+C<die()> calls within the code reference.
|
| -+
|
| -+Returns C<undef> if no C<die()> call was executed and C<$@> was unset, or the
|
| -+value of C<$@> if it was set. (The timeout event doesn't count as a C<die()>.)
|
| -+
|
| -+=cut
|
| -+
|
| -+sub run { $_[0]->_run($_[1], 0); }
|
| -+
|
| -+sub run_and_catch { $_[0]->_run($_[1], 1); }
|
| -+
|
| -+sub _run { # private
|
| -+ my ($self, $sub, $and_catch) = @_;
|
| -+
|
| -+ delete $self->{timed_out};
|
| -+
|
| -+ if (!$self->{secs}) { # no timeout! just call the sub and return.
|
| -+ return &$sub;
|
| -+ }
|
| -+
|
| -+ # assertion
|
| -+ if ($self->{secs} < 0) {
|
| -+ die "Mail::SpamAssassin::Timeout: oops? neg value for 'secs': $self->{secs}";
|
| -+ }
|
| -+
|
| -+ my $oldalarm = 0;
|
| -+ my $ret;
|
| -+
|
| -+ eval {
|
| -+ # note use of local to ensure closed scope here
|
| -+ local $SIG{ALRM} = sub { die "__alarm__ignore__\n" };
|
| -+ local $SIG{__DIE__}; # bug 4631
|
| -+
|
| -+ $oldalarm = alarm($self->{secs});
|
| -+
|
| -+ $ret = &$sub;
|
| -+
|
| -+ # Unset the alarm() before we leave eval{ } scope, as that stack-pop
|
| -+ # operation can take a second or two under load. Note: previous versions
|
| -+ # restored $oldalarm here; however, that is NOT what we want to do, since
|
| -+ # it creates a new race condition, namely that an old alarm could then fire
|
| -+ # while the stack-pop was underway, thereby appearing to be *this* timeout
|
| -+ # timing out. In terms of how we might possibly have nested timeouts in
|
| -+ # SpamAssassin, this is an academic issue with little impact, but it's
|
| -+ # still worth avoiding anyway.
|
| -+
|
| -+ alarm 0;
|
| -+ };
|
| -+
|
| -+ my $err = $@;
|
| -+
|
| -+ if (defined $oldalarm) {
|
| -+ # now, we could have died from a SIGALRM == timed out. if so,
|
| -+ # restore the previously-active one, or zero all timeouts if none
|
| -+ # were previously active.
|
| -+ alarm $oldalarm;
|
| -+ }
|
| -+
|
| -+ if ($err) {
|
| -+ if ($err =~ /__alarm__ignore__/) {
|
| -+ $self->{timed_out} = 1;
|
| -+ } else {
|
| -+ if ($and_catch) {
|
| -+ return $@;
|
| -+ } else {
|
| -+ die $@; # propagate any "real" errors
|
| -+ }
|
| -+ }
|
| -+ }
|
| -+
|
| -+ if ($and_catch) {
|
| -+ return; # undef
|
| -+ } else {
|
| -+ return $ret;
|
| -+ }
|
| -+}
|
| -+
|
| -+###########################################################################
|
| -+
|
| -+=item $t->timed_out()
|
| -+
|
| -+Returns C<1> if the most recent code executed in C<run()> timed out, or
|
| -+C<undef> if it did not.
|
| -+
|
| -+=cut
|
| -+
|
| -+sub timed_out {
|
| -+ my ($self) = @_;
|
| -+ return $self->{timed_out};
|
| -+}
|
| -+
|
| -+###########################################################################
|
| -+
|
| -+=item $t->reset()
|
| -+
|
| -+If called within a C<run()> code reference, causes the current alarm timer to
|
| -+be reset to its starting value.
|
| -+
|
| -+=cut
|
| -+
|
| -+sub reset {
|
| -+ my ($self) = @_;
|
| -+ alarm($self->{secs});
|
| -+}
|
| -+
|
| -+###########################################################################
|
| -+
|
| -+1;
|
| -
|
| -Modified: spamassassin/branches/3.1/spamd/spamd.raw
|
| -URL: http://svn.apache.org/viewcvs/spamassassin/branches/3.1/spamd/spamd.raw?rev=384590&r1=384589&r2=384590&view=diff
|
| -==============================================================================
|
| ---- spamassassin/branches/3.1/spamd/spamd.raw (original)
|
| -+++ spamassassin/branches/3.1/spamd/spamd.raw Thu Mar 9 11:51:59 2006
|
| -@@ -2049,6 +2049,9 @@
|
| - foreach (keys %children) {
|
| - kill 'INT' => $_;
|
| - my $pid = waitpid($_, 0);
|
| -+ if ($scaling) {
|
| -+ $scaling->child_exited($pid);
|
| -+ }
|
| - info("spamd: child $pid killed successfully");
|
| - }
|
| - %children = ();
|
| -
|
| -
|
| -
|
| -
|
| -
|
|
|