INN commit: trunk/nnrpd (nnrpd.c)

INN Commit Russ_Allbery at isc.org
Sat May 16 00:08:54 UTC 2009


    Date: Friday, May 15, 2009 @ 17:08:53
  Author: iulius
Revision: 8464

Fix a bug in previous commit 8463:  we have to use select()
for multiple sockets!  Otherwise, we have a huge CPU consumption.

Modified:
  trunk/nnrpd/nnrpd.c

---------+
 nnrpd.c |   80 ++++++++++++++++++++++++++++++++++++++++++++------------------
 1 file changed, 58 insertions(+), 22 deletions(-)

Modified: nnrpd.c
===================================================================
--- nnrpd.c	2009-05-15 20:31:54 UTC (rev 8463)
+++ nnrpd.c	2009-05-16 00:08:53 UTC (rev 8464)
@@ -852,9 +852,11 @@
     char                *ListenAddr = NULL;
     char                *ListenAddr6 = NULL;
     int			*lfds;
+    fd_set              lfdset, lfdsetread;
+    int                 lfdcount, lfdreadcount;
+    bool                lfdokay;
+    int                 lfdmax = 0;
     int                 fd = -1;
-    int                 fdcount;
-    bool                fdokay;
     pid_t		pid = -1;
     FILE                *pidfile;
     int			clienttimeout;
@@ -983,13 +985,13 @@
         /* Allocate an lfds array to hold the file descriptors
          * for IPv4 and/or IPv6 connections. */
         if (ListenAddr == NULL && ListenAddr6 == NULL) {
-            network_bind_all(ListenPort, &lfds, &fdcount);
+            network_bind_all(ListenPort, &lfds, &lfdcount);
         } else {
             if (ListenAddr != NULL && ListenAddr6 != NULL)
-                fdcount = 2;
+                lfdcount = 2;
             else
-                fdcount = 1;
-            lfds = xmalloc(fdcount * sizeof(int));
+                lfdcount = 1;
+            lfds = xmalloc(lfdcount * sizeof(int));
             i = 0;
             if (ListenAddr6 != NULL)
                 lfds[i++] = network_bind_ipv6(ListenAddr6, ListenPort);
@@ -998,13 +1000,13 @@
         }
 
         /* Bail if we couldn't listen on any sockets. */
-        fdokay = false;
-        for (i = 0; i < fdcount; i++) {
+        lfdokay = false;
+        for (i = 0; i < lfdcount; i++) {
             if (lfds[i] < 0)
                 continue;
-            fdokay = true;
+            lfdokay = true;
         }
-        if (!fdokay)
+        if (!lfdokay)
             die("can't bind to any addresses");
 
         /* If started as root, switch to news uid.  Unlike other parts of INN, we
@@ -1043,13 +1045,20 @@
  
 	setproctitle("accepting connections");
  	
-        for (i = 0; i < fdcount; i++) {
-            if (nonblocking(lfds[i], true) < 0)
-                syslog(L_ERROR, "can't nonblock %d %m", lfds[i]);
+        /* Initialize the listener file descriptors set. */
+        FD_ZERO(&lfdset);
+
+        for (i = 0; i < lfdcount; i++) {
             if (listen(lfds[i], 128) < 0) {
                 if (i != 0 && errno == EADDRINUSE)
                     continue;
                 syslog(L_ERROR, "can't listen to socket");
+            } else {
+                /* Remember the largest descriptor number
+                 * that is to be tested by select(). */
+                FD_SET(lfds[i], &lfdset);
+                if (lfdmax < lfds[i])
+                    lfdmax = lfds[i];
             }
         }
 
@@ -1061,10 +1070,25 @@
 		    pid = fork();
 		    if (pid == 0) {
 			do {
-                            for (i = 0; i < fdcount; i++) {
-                                fd = accept(lfds[i], NULL, NULL);
-                                if (fd >= 0)
-                                    break;
+                            fd = -1;
+
+                            /* Copy the master set because lfdsetread
+                             * will be modified. */
+                            lfdsetread = lfdset;
+                            lfdreadcount = select(lfdmax + 1, &lfdsetread,
+                                                  NULL, NULL, NULL);
+
+                            if (lfdreadcount > 0) {
+                                for (i = 0; i < lfdcount; i++) {
+                                    if (FD_ISSET(lfds[i], &lfdsetread)) {
+                                        fd = accept(lfds[i], NULL, NULL);
+                                        /* Only handle the first match.  Future
+                                         * calls to select() will handle possible
+                                         * other matches. */
+                                        if (fd >= 0)
+                                            break;
+                                    }
+                                }
                             }
 			} while (fd < 0);
 			break;
@@ -1083,10 +1107,22 @@
 	} else {
 	    /* Fork on demand. */
 	    do {
-                for (i = 0; i < fdcount; i++) {
-                    fd = accept(lfds[i], NULL, NULL);
-                    if (fd >= 0)
-                        break;
+                fd = -1;
+                
+                /* Copy the master set because lfdsetread will be modified. */
+                lfdsetread = lfdset;
+                lfdreadcount = select(lfdmax + 1, &lfdsetread, NULL, NULL, NULL);
+
+                if (lfdreadcount > 0) {
+                    for (i = 0; i < lfdcount; i++) {
+                        if (FD_ISSET(lfds[i], &lfdsetread)) {
+                            fd = accept(lfds[i], NULL, NULL);
+                            /* Only handle the first match.  Future calls
+                             * to select() will handle possible other matches. */
+                            if (fd >= 0)
+                                break;
+                        }
+                    }
                 }
 		if (fd < 0)
 		    continue;
@@ -1111,7 +1147,7 @@
 
 	/* Child process starts here. */
 	setproctitle("connected");
-        for (i = 0; i < fdcount; i++) {
+        for (i = 0; i < lfdcount; i++) {
             close(lfds[i]);
         }
 	dup2(fd, 0);




More information about the inn-committers mailing list