- 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");
- close(spamd_sock);
- fclose(mbox_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.
+ * Note: poll() is not supported in OSX 10.2 and is reported to be
+ * broken in more recent versions (up to 10.4).
+ */
+#ifndef NO_POLL_H
+ pollfd.fd = spamd_sock;
+ pollfd.events = POLLOUT;
+#endif
+ (void)fcntl(spamd_sock, F_SETFL, O_NONBLOCK);
+ do
+ {
+ read = fread(spamd_buffer,1,sizeof(spamd_buffer),mbox_file);
+ if (read > 0)
+ {
+ offset = 0;
+again:
+#ifndef NO_POLL_H
+ result = poll(&pollfd, 1, 1000);
+
+/* Patch posted by Erik ? for OS X and applied by PH */
+#else
+ select_tv.tv_sec = 1;
+ select_tv.tv_usec = 0;
+ FD_ZERO(&select_fd);
+ FD_SET(spamd_sock, &select_fd);
+ result = select(spamd_sock+1, NULL, &select_fd, NULL, &select_tv);
+#endif
+/* End Erik's patch */
+
+ if (result == -1 && errno == EINTR)
+ goto again;
+ else if (result < 1)
+ {
+ if (result == -1)
+ log_write(0, LOG_MAIN|LOG_PANIC,
+ "%s %s on spamd socket", loglabel, strerror(errno));
+ else
+ {
+ if (time(NULL) - start < SPAMD_TIMEOUT)
+ goto again;
+ log_write(0, LOG_MAIN|LOG_PANIC,
+ "%s timed out writing spamd socket", loglabel);
+ }
+ (void)close(spamd_sock);
+ (void)fclose(mbox_file);