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);

Reply via email to