From cfe75fc353d701560110e26fe3b1a6bab8cae2b4 Mon Sep 17 00:00:00 2001 From: Philip Hazel Date: Wed, 27 Apr 2005 10:00:18 +0000 Subject: [PATCH] Apply Ian Freislich's patch to fix a spamd timeout problem. --- doc/doc-txt/ChangeLog | 9 +++++- src/ACKNOWLEDGMENTS | 5 ++-- src/src/exim.h | 3 +- src/src/spam.c | 64 ++++++++++++++++++++++++++++++++++--------- src/src/spam.h | 6 ++-- 5 files changed, 67 insertions(+), 20 deletions(-) diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 758317801..0470f493b 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -1,4 +1,4 @@ -$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.123 2005/04/07 15:37:13 ph10 Exp $ +$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.124 2005/04/27 10:00:18 ph10 Exp $ Change log file for Exim from version 4.21 ------------------------------------------- @@ -230,6 +230,13 @@ PH/37 Exim used to check for duplicate addresses in the middle of routing, on still happens during the routing process, since they are not going to be routed further. +PH/38 Installed a patch from Ian Freislich, with the agreement of Tom Kistner. + It corrects a timeout issue with spamd. This is Ian's comment: "The + background is that sometimes spamd either never reads data from a + connection it has accepted, or it never writes response data. The exiscan + spam.[ch] uses a 3600 second timeout on spamd socket reads, further, it + blindly assumes that writes won't block so it may never time out." + A note about Exim versions 4.44 and 4.50 ---------------------------------------- diff --git a/src/ACKNOWLEDGMENTS b/src/ACKNOWLEDGMENTS index 8b7b704fb..acba7b758 100644 --- a/src/ACKNOWLEDGMENTS +++ b/src/ACKNOWLEDGMENTS @@ -1,4 +1,4 @@ -$Cambridge: exim/src/ACKNOWLEDGMENTS,v 1.22 2005/04/07 10:10:01 ph10 Exp $ +$Cambridge: exim/src/ACKNOWLEDGMENTS,v 1.23 2005/04/27 10:00:18 ph10 Exp $ EXIM ACKNOWLEDGEMENTS @@ -20,7 +20,7 @@ relatively small patches. Philip Hazel Lists created: 20 November 2002 -Last updated: 07 April 2005 +Last updated: 27 April 2005 THE OLD LIST @@ -127,6 +127,7 @@ Tony Finch Expansion extensions Patch for mxh lookup type in dnsdb Patch for defer_foo in dndsb Patch for ${dlfunc +Ian Freislich Patch for spamd timeout problem Giuliano Gavazzi Patches for OSX compilation Dominic Germain Patch for exiqgrep MacOS X bug Oliver Gorwits $load_average patch diff --git a/src/src/exim.h b/src/src/exim.h index b28edb79b..e44cad788 100644 --- a/src/src/exim.h +++ b/src/src/exim.h @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/exim.h,v 1.10 2005/03/22 14:11:54 ph10 Exp $ */ +/* $Cambridge: exim/src/src/exim.h,v 1.11 2005/04/27 10:00:18 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -92,6 +92,7 @@ making unique names. */ #include #include #include +#include #include #include #include diff --git a/src/src/spam.c b/src/src/spam.c index 77406cea4..0f6ad1434 100644 --- a/src/src/spam.c +++ b/src/src/spam.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/spam.c,v 1.4 2005/02/17 11:58:26 ph10 Exp $ */ +/* $Cambridge: exim/src/src/spam.c,v 1.5 2005/04/27 10:00:18 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -30,14 +30,17 @@ int spam(uschar **listptr) { FILE *mbox_file; int spamd_sock; uschar spamd_buffer[32600]; - int i, j, offset; + int i, j, offset, result; uschar spamd_version[8]; uschar spamd_score_char; double spamd_threshold, spamd_score; int spamd_report_offset; uschar *p,*q; int override = 0; + time_t start; + size_t read, wrote; struct sockaddr_un server; + struct pollfd pollfd; /* find the username from the option list */ if ((user_name = string_nextinlist(&list, &sep, @@ -77,6 +80,7 @@ int spam(uschar **listptr) { return DEFER; }; + start = time(NULL); /* socket does not start with '/' -> network socket */ if (*spamd_address != '/') { time_t now = time(NULL); @@ -203,33 +207,67 @@ int spam(uschar **listptr) { }; /* now send the file */ + /* spamd sometimes accepts conections but doesn't read data off + * the connection. We make the file descriptor non-blocking so + * that the write will only write sufficient data without blocking + * and we poll the desciptor to make sure that we can write without + * blocking. Short writes are gracefully handled and if the whole + * trasaction takes too long it is aborted. + */ + pollfd.fd = spamd_sock; + pollfd.events = POLLOUT; + fcntl(spamd_sock, F_SETFL, O_NONBLOCK); do { - j = fread(spamd_buffer,1,sizeof(spamd_buffer),mbox_file); - if (j > 0) { - i = send(spamd_sock,spamd_buffer,j,0); - if (i != j) { - log_write(0, LOG_MAIN|LOG_PANIC, - "spam acl condition: error/short send to spamd"); + read = fread(spamd_buffer,1,sizeof(spamd_buffer),mbox_file); + if (read > 0) { + offset = 0; +again: + result = poll(&pollfd, 1, 1000); + if (result == -1 && errno == EINTR) + continue; + else if (result < 1) { + if (result == -1) + log_write(0, LOG_MAIN|LOG_PANIC, + "spam acl condition: %s on spamd socket", strerror(errno)); + else { + if (time(NULL) - start < SPAMD_TIMEOUT) + goto again; + log_write(0, LOG_MAIN|LOG_PANIC, + "spam acl condition: timed out writing spamd socket"); + } close(spamd_sock); fclose(mbox_file); return DEFER; - }; - }; + } + wrote = send(spamd_sock,spamd_buffer + offset,read - offset,0); + if (offset + wrote != read) { + offset += wrote; + goto again; + } + } + } + while (!feof(mbox_file) && !ferror(mbox_file)); + if (ferror(mbox_file)) { + log_write(0, LOG_MAIN|LOG_PANIC, + "spam acl condition: error reading spool file: %s", strerror(errno)); + close(spamd_sock); + fclose(mbox_file); + return DEFER; } - while (j > 0); fclose(mbox_file); /* we're done sending, close socket for writing */ shutdown(spamd_sock,SHUT_WR); - /* read spamd response */ + /* read spamd response using what's left of the timeout. + */ memset(spamd_buffer, 0, sizeof(spamd_buffer)); offset = 0; while((i = ip_recv(spamd_sock, spamd_buffer + offset, sizeof(spamd_buffer) - offset - 1, - SPAMD_READ_TIMEOUT)) > 0 ) { + SPAMD_TIMEOUT - time(NULL) + start)) > 0 ) { offset += i; } diff --git a/src/src/spam.h b/src/src/spam.h index b2a12e347..b1c8313c3 100644 --- a/src/src/spam.h +++ b/src/src/spam.h @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/spam.h,v 1.2 2004/12/16 15:11:47 tom Exp $ */ +/* $Cambridge: exim/src/src/spam.h,v 1.3 2005/04/27 10:00:18 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -11,8 +11,8 @@ #ifdef WITH_CONTENT_SCAN -/* timeout for reading from spamd */ -#define SPAMD_READ_TIMEOUT 3600 +/* timeout for reading and writing spamd */ +#define SPAMD_TIMEOUT 120 /* maximum length of the spam bar */ #define MAX_SPAM_BAR_CHARS 50 -- 2.30.2