ph10 2005/04/27 11:00:18 BST
Modified files:
exim-doc/doc-txt ChangeLog
exim-src ACKNOWLEDGMENTS
exim-src/src exim.h spam.c spam.h
Log:
Apply Ian Freislich's patch to fix a spamd timeout problem.
Revision Changes Path
1.124 +7 -0 exim/exim-doc/doc-txt/ChangeLog
1.23 +2 -1 exim/exim-src/ACKNOWLEDGMENTS
1.11 +1 -0 exim/exim-src/src/exim.h
1.5 +50 -12 exim/exim-src/src/spam.c
1.3 +2 -2 exim/exim-src/src/spam.h
Index: ChangeLog
===================================================================
RCS file: /home/cvs/exim/exim-doc/doc-txt/ChangeLog,v
retrieving revision 1.123
retrieving revision 1.124
diff -u -r1.123 -r1.124
--- ChangeLog 7 Apr 2005 15:37:13 -0000 1.123
+++ ChangeLog 27 Apr 2005 10:00:18 -0000 1.124
@@ -1,4 +1,4 @@
-$Cambridge: exim/exim-doc/doc-txt/ChangeLog,v 1.123 2005/04/07 15:37:13 ph10 Exp $
+$Cambridge: exim/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
-------------------------------------------
@@ -229,6 +229,13 @@
For deliveries to pipes, files, and autoreplies, the duplicate checking
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
Index: ACKNOWLEDGMENTS
===================================================================
RCS file: /home/cvs/exim/exim-src/ACKNOWLEDGMENTS,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -r1.22 -r1.23
--- ACKNOWLEDGMENTS 7 Apr 2005 10:10:01 -0000 1.22
+++ ACKNOWLEDGMENTS 27 Apr 2005 10:00:18 -0000 1.23
@@ -1,4 +1,4 @@
-$Cambridge: exim/exim-src/ACKNOWLEDGMENTS,v 1.22 2005/04/07 10:10:01 ph10 Exp $
+$Cambridge: exim/exim-src/ACKNOWLEDGMENTS,v 1.23 2005/04/27 10:00:18 ph10 Exp $
EXIM ACKNOWLEDGEMENTS
@@ -20,7 +20,7 @@
Philip Hazel
Lists created: 20 November 2002
-Last updated: 07 April 2005
+Last updated: 27 April 2005
THE OLD LIST
@@ -127,6 +127,7 @@
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
Index: exim.h
===================================================================
RCS file: /home/cvs/exim/exim-src/src/exim.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- exim.h 22 Mar 2005 14:11:54 -0000 1.10
+++ exim.h 27 Apr 2005 10:00:18 -0000 1.11
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/exim.h,v 1.10 2005/03/22 14:11:54 ph10 Exp $ */
+/* $Cambridge: exim/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 @@
#include <sys/file.h>
#include <dirent.h>
#include <netdb.h>
+#include <poll.h>
#include <pwd.h>
#include <grp.h>
#include <syslog.h>
Index: spam.c
===================================================================
RCS file: /home/cvs/exim/exim-src/src/spam.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- spam.c 17 Feb 2005 11:58:26 -0000 1.4
+++ spam.c 27 Apr 2005 10:00:18 -0000 1.5
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/spam.c,v 1.4 2005/02/17 11:58:26 ph10 Exp $ */
+/* $Cambridge: exim/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 @@
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 @@
return DEFER;
};
+ start = time(NULL);
/* socket does not start with '/' -> network socket */
if (*spamd_address != '/') {
time_t now = time(NULL);
@@ -203,33 +207,67 @@
};
/* 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;
}
Index: spam.h
===================================================================
RCS file: /home/cvs/exim/exim-src/src/spam.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- spam.h 16 Dec 2004 15:11:47 -0000 1.2
+++ spam.h 27 Apr 2005 10:00:18 -0000 1.3
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/spam.h,v 1.2 2004/12/16 15:11:47 tom Exp $ */
+/* $Cambridge: exim/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