summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ACKNOWLEDGMENTS5
-rw-r--r--src/src/exim.h3
-rw-r--r--src/src/spam.c64
-rw-r--r--src/src/spam.h6
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