Since upgrading to 3.4.0 from 3.3.2 we've seen problems with all of the
spamd children blocking (for a yet unknown reason) for long enough that
the clients all give up and retry another server. Eventually, the spamd
child hits its internal timeout and then goes of and blocks indefinitely
while trying to write to the client (which is gone) that it timed out.
This particular situation can be avoided in part by ensuring that the
spamd timeout is lower than the spamc timeout.
This is quick patch to fix this so service_timeout() is guarded with an
alarm but I don't think it is the only write to a client that needs it.
diff -u /usr/bin/spamd.orig /usr/bin/spamd
--- /usr/bin/spamd.orig 2014-07-01 15:44:43.281790649 -0700
+++ /usr/bin/spamd 2014-07-01 15:50:15.183431230 -0700
@@ -2413,8 +2413,24 @@
sub service_timeout {
my ($err) = @_;
my $resp = "EX_TIMEOUT";
- print $client "SPAMD/1.0 $resphash{$resp} Timeout: $err\r\n";
warn("spamd: timeout: $err\n");
+
+ eval {
+ Mail::SpamAssassin::Util::trap_sigalrm_fully(sub {
+ die "Timeout sending EX_TIMEOUT $err to client";
+ });
+ alarm 1;
+ print $client "SPAMD/1.0 $resphash{$resp} Timeout: $err\r\n";
+ };
+ alarm 0;
+
+ if ($@) {
+ die "spamd: $@";
+ }
+
+ $client->close;
+
+ return 1;
}