src/rrdd.c: Implement listening on multiple sockets.
authorFlorian Forster <octo@leeloo.home.verplant.org>
Sun, 22 Jun 2008 11:28:52 +0000 (13:28 +0200)
committerFlorian Forster <octo@leeloo.home.verplant.org>
Sun, 22 Jun 2008 11:28:52 +0000 (13:28 +0200)
src/rrdd.c

index 6ce6b10..7cd2431 100644 (file)
@@ -614,6 +614,8 @@ static int close_listen_sockets (void) /* {{{ */
 static void *listen_thread_main (void *args) /* {{{ */
 {
   char buffer[4096];
+  struct pollfd *pollfds;
+  int pollfds_num;
   int status;
   int i;
 
@@ -631,47 +633,87 @@ static void *listen_thread_main (void *args) /* {{{ */
     return (NULL);
   }
 
-  while (do_shutdown == 0)
+  pollfds_num = listen_fds_num;
+  pollfds = (struct pollfd *) malloc (sizeof (*pollfds) * pollfds_num);
+  if (pollfds == NULL)
   {
-    int *client_sd;
-    struct sockaddr_storage client_sa;
-    socklen_t client_sa_size;
-    pthread_t tid;
+    RRDD_LOG (LOG_ERR, "listen_thread_main: malloc failed.");
+    return (NULL);
+  }
+  memset (pollfds, 0, sizeof (*pollfds) * pollfds_num);
 
-    client_sd = (int *) malloc (sizeof (int));
-    if (client_sd == NULL)
+  while (do_shutdown == 0)
+  {
+    assert (pollfds_num == listen_fds_num);
+    for (i = 0; i < pollfds_num; i++)
     {
-      RRDD_LOG (LOG_ERR, "listen_thread_main: malloc failed.");
-      sleep (120);
-      continue;
+      pollfds[i].fd = listen_fds[i].fd;
+      pollfds[i].events = POLLIN | POLLPRI;
+      pollfds[i].revents = 0;
     }
 
-    client_sa_size = sizeof (client_sa);
-    /* FIXME: Don't implement listen_fds as a list or use poll(2) here! */
-    *client_sd = accept (listen_fds[0].fd,
-        (struct sockaddr *) &client_sa, &client_sa_size);
-    if (*client_sd < 0)
+    status = poll (pollfds, pollfds_num, /* timeout = */ -1);
+    if (status < 1)
     {
-      RRDD_LOG (LOG_ERR, "listen_thread_main: accept(2) failed.");
+      status = errno;
+      if (status != EINTR)
+      {
+        RRDD_LOG (LOG_ERR, "listen_thread_main: poll(2) failed.");
+      }
       continue;
     }
 
-    RRDD_LOG (LOG_DEBUG, "listen_thread_main: accept(2) returned fd #%i.",
-        *client_sd);
-
-    status = pthread_create (&tid, /* attr = */ NULL, connection_thread_main,
-        /* args = */ (void *) client_sd);
-    if (status != 0)
+    for (i = 0; i < pollfds_num; i++)
     {
-      RRDD_LOG (LOG_ERR, "listen_thread_main: pthread_create failed.");
-      close (*client_sd);
-      free (client_sd);
-      continue;
-    }
+      int *client_sd;
+      struct sockaddr_storage client_sa;
+      socklen_t client_sa_size;
+      pthread_t tid;
+
+      if (pollfds[i].revents == 0)
+        continue;
+
+      if ((pollfds[i].revents & (POLLIN | POLLPRI)) == 0)
+      {
+        RRDD_LOG (LOG_ERR, "listen_thread_main: "
+            "poll(2) returned something unexpected for listen FD #%i.",
+            pollfds[i].fd);
+        continue;
+      }
+
+      client_sd = (int *) malloc (sizeof (int));
+      if (client_sd == NULL)
+      {
+        RRDD_LOG (LOG_ERR, "listen_thread_main: malloc failed.");
+        continue;
+      }
+
+      client_sa_size = sizeof (client_sa);
+      *client_sd = accept (pollfds[i].fd,
+          (struct sockaddr *) &client_sa, &client_sa_size);
+      if (*client_sd < 0)
+      {
+        RRDD_LOG (LOG_ERR, "listen_thread_main: accept(2) failed.");
+        continue;
+      }
+
+      RRDD_LOG (LOG_DEBUG, "listen_thread_main: accept(2) returned fd #%i.",
+          *client_sd);
+
+      status = pthread_create (&tid, /* attr = */ NULL, connection_thread_main,
+          /* args = */ (void *) client_sd);
+      if (status != 0)
+      {
+        RRDD_LOG (LOG_ERR, "listen_thread_main: pthread_create failed.");
+        close (*client_sd);
+        free (client_sd);
+        continue;
+      }
 
-    RRDD_LOG (LOG_DEBUG, "listen_thread_main: pthread_create succeeded: "
-        "tid = %lu",
-        *((unsigned long *) &tid));
+      RRDD_LOG (LOG_DEBUG, "listen_thread_main: pthread_create succeeded: "
+          "tid = %lu",
+          *((unsigned long *) &tid));
+    } /* for (pollfds_num) */
   } /* while (do_shutdown == 0) */
 
   close_listen_sockets ();