On Wed, Feb 22, 2006 at 11:28:32AM +0100, Francesco P. Lovergine wrote:
> tags 353965 + upstream
> thanks
>
> It seems a job for sendfile(2)...
>
> On Wed, Feb 22, 2006 at 08:16:26PM +1000, Andrew Meaden wrote:
> > imapfilter utilises as much CPU as it can get its hands on while moving
> > email from one imap server (locally accessable via the loopback
> > interface) to a remote one. The process appears to correctly perform
> > it's job, and the bottleneck is still the upsteam speed of my internet
> > link; however for the duration of this upload, the process sits on 99.2%
> > CPU, only releasing some when anything else requires it.
> >
> > This also causes the load on the machine to climb to 1 higher than it
> > started, and apart from causing relatively minor slowdowns elsewhere in
> > the machine, does not seem to impede the success of the imapfilter run.
> >
> > If I lower my upstream rate by 75%, the process uses 400% more CPU time
> > (overall) to run. If I enable compression on the VPN link, the CPU time
> > required drops also, keeping the link between the process and the remote
> > IMAP server completely utilised.
Hello,
I think I know what is causing this problem...
I'm attaching a patch...
Thanks
diff -ruN imapfilter-1.1.1.orig/socket.c imapfilter-1.1.1/socket.c
--- imapfilter-1.1.1.orig/socket.c 2005-11-11 01:21:37.000000000 +0200
+++ imapfilter-1.1.1/socket.c 2006-02-22 13:25:43.000000000 +0200
@@ -193,11 +193,9 @@
memset(buf, 0, len + 1);
t = (int)(get_option_number("timeout"));
- if (t > 0) {
- tv.tv_sec = t;
- tv.tv_usec = 0;
+ if (t > 0)
tvp = &tv;
- }
+
f = fcntl(ssn->socket, F_GETFL, 0);
fcntl(ssn->socket, F_SETFL, f | O_NONBLOCK);
@@ -206,32 +204,43 @@
#ifndef NO_SSLTLS
if (ssn->ssl) {
- while (SSL_pending(ssn->ssl) > 0 || ((s =
- select(ssn->socket + 1, &fds, NULL, NULL, tvp)) > 0 &&
- FD_ISSET(ssn->socket, &fds))) {
- r = (ssize_t) SSL_read(ssn->ssl, buf, len);
-
- if (r > 0)
- break;
-
- switch (SSL_get_error(ssn->ssl, r)) {
- case SSL_ERROR_WANT_READ:
- case SSL_ERROR_WANT_WRITE:
- continue;
- case SSL_ERROR_ZERO_RETURN:
- goto fail;
- case SSL_ERROR_SYSCALL:
- case SSL_ERROR_SSL:
- error("reading data; %s\n",
- ERR_error_string(ERR_get_error(), NULL));
- goto fail;
- default:
- goto fail;
+ do {
+ if (t > 0) {
+ tv.tv_sec = t;
+ tv.tv_usec = 0;
}
- }
+ if ((s = select(ssn->socket + 1, &fds, NULL, NULL,
+ tvp)) > 0 && FD_ISSET(ssn->socket, &fds)) {
+ r = (ssize_t) SSL_read(ssn->ssl, buf, len);
+
+ if (r > 0)
+ continue;
+
+ switch (SSL_get_error(ssn->ssl, r)) {
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ continue;
+ case SSL_ERROR_ZERO_RETURN:
+ goto fail;
+ case SSL_ERROR_SYSCALL:
+ case SSL_ERROR_SSL:
+ error("reading data; %s\n",
+ ERR_error_string(ERR_get_error(),
+ NULL));
+ goto fail;
+ default:
+ goto fail;
+ }
+ }
+ } while (SSL_pending(ssn->ssl) > 0);
} else
#endif
{
+ if (t > 0) {
+ tv.tv_sec = t;
+ tv.tv_usec = 0;
+ }
+
if ((s = select(ssn->socket + 1, &fds, NULL, NULL, tvp)) > 0 &&
FD_ISSET(ssn->socket, &fds))
r = read(ssn->socket, buf, len);
@@ -281,11 +290,9 @@
s = 1;
t = (int)(get_option_number("timeout"));
- if (t > 0) {
- tv.tv_sec = t;
- tv.tv_usec = 0;
+ if (t > 0)
tvp = &tv;
- }
+
f = fcntl(ssn->socket, F_GETFL, 0);
fcntl(ssn->socket, F_SETFL, f | O_NONBLOCK);
@@ -295,12 +302,17 @@
while (len) {
#ifndef NO_SSLTLS
if (ssn->ssl) {
- while ((s = select(ssn->socket + 1, NULL, &fds, NULL,
+ if (t > 0) {
+ tv.tv_sec = t;
+ tv.tv_usec = 0;
+ }
+
+ if ((s = select(ssn->socket + 1, NULL, &fds, NULL,
tvp) > 0 && FD_ISSET(ssn->socket, &fds))) {
w = (ssize_t) SSL_write(ssn->ssl, buf, len);
if (w > 0)
- break;
+ continue;
switch (SSL_get_error(ssn->ssl, w)) {
case SSL_ERROR_WANT_READ:
@@ -323,6 +335,11 @@
} else
#endif
{
+ if (t > 0) {
+ tv.tv_sec = t;
+ tv.tv_usec = 0;
+ }
+
if ((s = select(ssn->socket + 1, NULL, &fds, NULL,
tvp)) > 0 && FD_ISSET(ssn->socket, &fds))
w = write(ssn->socket, buf, len);