diff options
author | Philip Hazel <ph10@hermes.cam.ac.uk> | 2005-04-27 10:00:18 +0000 |
---|---|---|
committer | Philip Hazel <ph10@hermes.cam.ac.uk> | 2005-04-27 10:00:18 +0000 |
commit | cfe75fc353d701560110e26fe3b1a6bab8cae2b4 (patch) | |
tree | 5d5ec7f15031f005e34b75200e926482e11ce0dc /src | |
parent | c37737e34f7e14fd0482252ec387c3e0200358a2 (diff) |
Apply Ian Freislich's patch to fix a spamd timeout problem.
Diffstat (limited to 'src')
-rw-r--r-- | src/ACKNOWLEDGMENTS | 5 | ||||
-rw-r--r-- | src/src/exim.h | 3 | ||||
-rw-r--r-- | src/src/spam.c | 64 | ||||
-rw-r--r-- | src/src/spam.h | 6 |
4 files changed, 59 insertions, 19 deletions
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 <sys/file.h> #include <dirent.h> #include <netdb.h> +#include <poll.h> #include <pwd.h> #include <grp.h> #include <syslog.h> 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 |