gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r9463 - in libmicrohttpd: . doc src/daemon src/include


From: gnunet
Subject: [GNUnet-SVN] r9463 - in libmicrohttpd: . doc src/daemon src/include
Date: Wed, 11 Nov 2009 04:55:34 -0700

Author: grothoff
Date: 2009-11-11 04:55:34 -0700 (Wed, 11 Nov 2009)
New Revision: 9463

Modified:
   libmicrohttpd/AUTHORS
   libmicrohttpd/ChangeLog
   libmicrohttpd/doc/microhttpd.texi
   libmicrohttpd/src/daemon/connection.c
   libmicrohttpd/src/daemon/connection.h
   libmicrohttpd/src/daemon/daemon.c
   libmicrohttpd/src/daemon/internal.h
   libmicrohttpd/src/include/microhttpd.h
Log:
[libmicrohttpd] large file descriptors
From: 
John Muth <address@hidden>
  To: 
address@hidden
  Date: 
Yesterday 18:35:25

Hi Christian,

We are using libmicro http in our application. Our application runs on Linux
and uses a large number of file descriptors (> 1024). Unfortunately the
Linux fdset's only have room for 1024 fd's.

I made changes to the 0.4.4 source to support poll instead of select so we
could get around the file descriptor issue. I've attached the diffs if you
are interested.

-John Muth
Parascale


Modified: libmicrohttpd/AUTHORS
===================================================================
--- libmicrohttpd/AUTHORS       2009-11-10 22:21:57 UTC (rev 9462)
+++ libmicrohttpd/AUTHORS       2009-11-11 11:55:34 UTC (rev 9463)
@@ -21,6 +21,7 @@
 David Reiss <address@hidden>
 Mika Raento <address@hidden>
 Mike Crowe <address@hidden>
+John Muth <address@hidden>
 
 Documentation contributions also came from:
 Marco Maggi <address@hidden>

Modified: libmicrohttpd/ChangeLog
===================================================================
--- libmicrohttpd/ChangeLog     2009-11-10 22:21:57 UTC (rev 9462)
+++ libmicrohttpd/ChangeLog     2009-11-11 11:55:34 UTC (rev 9463)
@@ -1,3 +1,7 @@
+Wed Nov 11 12:54:16 CET 2009
+       Adding support for poll (alternative to select allowing
+       for more than FD_SETSIZE parallel connections). -JM
+
 Wed Oct 28 20:26:00 CET 2009
        Releasing libmicrohttpd 0.4.4. -CG
 

Modified: libmicrohttpd/doc/microhttpd.texi
===================================================================
--- libmicrohttpd/doc/microhttpd.texi   2009-11-10 22:21:57 UTC (rev 9462)
+++ libmicrohttpd/doc/microhttpd.texi   2009-11-11 11:55:34 UTC (rev 9463)
@@ -244,6 +244,15 @@
 in what you accept'' norm.  It is recommended to turn this @strong{ON}
 if you are testing clients against @mhd{}, and @strong{OFF} in
 production.
+
address@hidden MHD_USE_POLL
address@hidden FD_SETSIZE
address@hidden poll
address@hidden select
+Use poll instead of select. This allows sockets with descriptors
address@hidden>= FD_SETSIZE}.  This option only works in conjunction with
address@hidden (at this point).
+
 @end table
 @end deftp
 

Modified: libmicrohttpd/src/daemon/connection.c
===================================================================
--- libmicrohttpd/src/daemon/connection.c       2009-11-10 22:21:57 UTC (rev 
9462)
+++ libmicrohttpd/src/daemon/connection.c       2009-11-11 11:55:34 UTC (rev 
9463)
@@ -702,6 +702,29 @@
                           fd_set * write_fd_set,
                           fd_set * except_fd_set, int *max_fd)
 {
+  int ret;
+  struct MHD_Pollfd p;
+
+  memset(&p, 0, sizeof(struct MHD_Pollfd));
+  ret = MHD_connection_get_pollfd(connection, &p);
+  if ( (ret == MHD_YES) && (p.fd >= 0) ) {
+    if (0 != (p.events & MHD_POLL_ACTION_IN)) 
+      do_fd_set(p.fd, read_fd_set, max_fd);    
+    if (0 != (p.events & MHD_POLL_ACTION_OUT)) 
+      do_fd_set(p.fd, write_fd_set, max_fd);    
+  }
+  return ret;
+}
+
+/**
+ * Obtain the pollfd for this connection
+ *
+ * @return MHD_YES on success. If return MHD_YES and p->fd < 0, this 
+ *                 connection is not waiting for any read or write events
+ */
+int
+MHD_connection_get_pollfd(struct MHD_Connection *connection, struct MHD_Pollfd 
*p)
+{
   int fd;
 
   if (connection->pool == NULL)
@@ -715,6 +738,7 @@
       return MHD_NO;
     }
   fd = connection->socket_fd;
+  p->fd = fd;
   if (fd == -1)
     return MHD_YES;
   while (1)
@@ -750,7 +774,7 @@
               continue;
             }
           if (MHD_NO == connection->read_closed)
-            do_fd_set (fd, read_fd_set, max_fd);
+            p->events |= MHD_POLL_ACTION_IN;
           break;
         case MHD_CONNECTION_HEADERS_RECEIVED:
           /* we should never get here */
@@ -760,7 +784,7 @@
           EXTRA_CHECK (0);
           break;
         case MHD_CONNECTION_CONTINUE_SENDING:
-          do_fd_set (fd, write_fd_set, max_fd);
+          p->events |= MHD_POLL_ACTION_OUT;
           break;
         case MHD_CONNECTION_CONTINUE_SENT:
           if (connection->read_buffer_offset == connection->read_buffer_size)
@@ -789,7 +813,7 @@
             }
           if ((connection->read_buffer_offset < connection->read_buffer_size)
               && (MHD_NO == connection->read_closed))
-            do_fd_set (fd, read_fd_set, max_fd);
+            p->events |= MHD_POLL_ACTION_IN;
           break;
         case MHD_CONNECTION_BODY_RECEIVED:
         case MHD_CONNECTION_FOOTER_PART_RECEIVED:
@@ -800,7 +824,7 @@
               connection->state = MHD_CONNECTION_CLOSED;
               continue;
             }
-          do_fd_set (fd, read_fd_set, max_fd);
+          p->events |= MHD_POLL_ACTION_IN;
           /* transition to FOOTERS_RECEIVED
              happens in read handler */
           break;
@@ -810,19 +834,19 @@
           break;
         case MHD_CONNECTION_HEADERS_SENDING:
           /* headers in buffer, keep writing */
-          do_fd_set (fd, write_fd_set, max_fd);
+          p->events |= MHD_POLL_ACTION_OUT;
           break;
         case MHD_CONNECTION_HEADERS_SENT:
           EXTRA_CHECK (0);
           break;
         case MHD_CONNECTION_NORMAL_BODY_READY:
-          do_fd_set (fd, write_fd_set, max_fd);
+          p->events |= MHD_POLL_ACTION_OUT;
           break;
         case MHD_CONNECTION_NORMAL_BODY_UNREADY:
           /* not ready, no socket action */
           break;
         case MHD_CONNECTION_CHUNKED_BODY_READY:
-          do_fd_set (fd, write_fd_set, max_fd);
+          p->events |= MHD_POLL_ACTION_OUT;
           break;
         case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
           /* not ready, no socket action */
@@ -831,7 +855,7 @@
           EXTRA_CHECK (0);
           break;
         case MHD_CONNECTION_FOOTERS_SENDING:
-          do_fd_set (fd, write_fd_set, max_fd);
+          p->events |= MHD_POLL_ACTION_OUT;
           break;
         case MHD_CONNECTION_FOOTERS_SENT:
           EXTRA_CHECK (0);

Modified: libmicrohttpd/src/daemon/connection.h
===================================================================
--- libmicrohttpd/src/daemon/connection.h       2009-11-10 22:21:57 UTC (rev 
9462)
+++ libmicrohttpd/src/daemon/connection.h       2009-11-11 11:55:34 UTC (rev 
9463)
@@ -40,6 +40,14 @@
                           fd_set * write_fd_set,
                           fd_set * except_fd_set, int *max_fd);
 
+/**
+ * Obtain the pollfd for this connection. The poll interface allows large
+ * file descriptors. Select goes stupid when the fd overflows fdset (which
+ * is fixed).
+ */
+int MHD_connection_get_pollfd(struct MHD_Connection *connection,
+                              struct MHD_Pollfd *p);
+
 void MHD_set_http_calbacks (struct MHD_Connection *connection);
 
 int MHD_connection_handle_read (struct MHD_Connection *connection);

Modified: libmicrohttpd/src/daemon/daemon.c
===================================================================
--- libmicrohttpd/src/daemon/daemon.c   2009-11-10 22:21:57 UTC (rev 9462)
+++ libmicrohttpd/src/daemon/daemon.c   2009-11-11 11:55:34 UTC (rev 9463)
@@ -36,6 +36,8 @@
 #include "gnutls_global.h"
 #endif
 
+#include <poll.h>
+
 /**
  * Default connection limit.
  */
@@ -437,7 +439,8 @@
   if ((daemon == NULL) || (read_fd_set == NULL) || (write_fd_set == NULL)
       || (except_fd_set == NULL) || (max_fd == NULL)
       || (-1 == (fd = daemon->socket_fd)) || (daemon->shutdown == MHD_YES)
-      || ((daemon->options & MHD_USE_THREAD_PER_CONNECTION) != 0))
+      || ((daemon->options & MHD_USE_THREAD_PER_CONNECTION) != 0)
+      || ((daemon->options & MHD_USE_POLL) != 0))
     return MHD_NO;
 
   FD_SET (fd, read_fd_set);
@@ -463,7 +466,7 @@
 
 /**
  * Main function of the thread that handles an individual
- * connection.
+ * connection when MHD_USE_THREAD_PER_CONNECTION.
  */
 static void *
 MHD_handle_connection (void *data)
@@ -477,17 +480,13 @@
   struct timeval tv;
   unsigned int timeout;
   unsigned int now;
+  struct MHD_Pollfd mp;
+  struct pollfd p;
 
   if (con == NULL)
     mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
   timeout = con->daemon->connection_timeout;
-  while ((!con->daemon->shutdown) && (con->socket_fd != -1))
-    {
-      FD_ZERO (&rs);
-      FD_ZERO (&ws);
-      FD_ZERO (&es);
-      max = 0;
-      MHD_connection_get_fdset (con, &rs, &ws, &es, &max);
+  while ((!con->daemon->shutdown) && (con->socket_fd != -1)) {
       now = time (NULL);
       tv.tv_usec = 0;
       if (timeout > (now - con->last_activity))
@@ -506,24 +505,63 @@
        {
          tv.tv_sec = 0;
        }
-      num_ready = SELECT (max + 1, &rs, &ws, &es, &tv);
-      if (num_ready < 0)
-        {
+      if (0 == (con->daemon->options & MHD_USE_POLL)) {
+       /* use select */
+        FD_ZERO (&rs);
+        FD_ZERO (&ws);
+        FD_ZERO (&es);
+        max = 0;
+        MHD_connection_get_fdset (con, &rs, &ws, &es, &max);
+        num_ready = SELECT (max + 1, &rs, &ws, &es, &tv);
+        if (num_ready < 0) {
+            if (errno == EINTR)
+              continue;
+#if HAVE_MESSAGES
+            MHD_DLOG (con->daemon, "Error during select (%d): `%s'\n", max,
+                      STRERROR (errno));
+#endif
+            break;
+        }
+        /* call appropriate connection handler if necessary */
+        if ((con->socket_fd != -1) && (FD_ISSET (con->socket_fd, &rs)))
+          con->read_handler (con);
+        if ((con->socket_fd != -1) && (FD_ISSET (con->socket_fd, &ws)))
+          con->write_handler (con);
+        if (con->socket_fd != -1)
+          con->idle_handler (con);
+      } else {
+        /* use poll */
+        memset(&mp, 0, sizeof (struct MHD_Pollfd));
+        MHD_connection_get_pollfd(con, &mp);
+       memset(&p, 0, sizeof (struct pollfd));
+        p.fd = mp.fd;
+        if (mp.events & MHD_POLL_ACTION_IN) 
+          p.events |= POLLIN;        
+        if (mp.events & MHD_POLL_ACTION_OUT) 
+          p.events |= POLLOUT;
+       /* in case we are missing the SIGALRM, keep going after
+          at most 1s */
+       if (poll (&p, 1, 1000) < 0) {
           if (errno == EINTR)
             continue;
 #if HAVE_MESSAGES
-          MHD_DLOG (con->daemon, "Error during select (%d): `%s'\n", max,
+          MHD_DLOG (con->daemon, "Error during poll: `%s'\n", 
                     STRERROR (errno));
 #endif
           break;
         }
-      /* call appropriate connection handler if necessary */
-      if ((con->socket_fd != -1) && (FD_ISSET (con->socket_fd, &rs)))
-        con->read_handler (con);
-      if ((con->socket_fd != -1) && (FD_ISSET (con->socket_fd, &ws)))
-        con->write_handler (con);
-      if (con->socket_fd != -1)
-        con->idle_handler (con);
+        if ( (con->socket_fd != -1) && 
+            (0 != (p.revents & POLLIN)) ) 
+          con->read_handler (con);        
+        if ( (con->socket_fd != -1) && 
+            (0 != (p.revents & POLLOUT)) )
+          con->write_handler (con);        
+        if (con->socket_fd != -1)
+          con->idle_handler (con);
+       if ( (con->socket_fd != -1) &&
+            (0 != (p.revents & (POLLERR | POLLHUP))) )
+          MHD_connection_close (con, MHD_REQUEST_TERMINATED_WITH_ERROR);      
+      }
     }
   if (con->socket_fd != -1)
     {
@@ -622,7 +660,8 @@
       return MHD_NO;
     }
 #ifndef WINDOWS
-  if (s >= FD_SETSIZE)
+  if ( (s >= FD_SETSIZE) &&
+       (0 == daemon->options & MHD_USE_POLL) )
     {
 #if HAVE_MESSAGES
       MHD_DLOG (daemon,
@@ -986,6 +1025,38 @@
 }
 
 /**
+ * Poll for new connection. Used only with THREAD_PER_CONNECTION
+ */
+static int
+MHD_poll (struct MHD_Daemon *daemon)
+{
+  struct pollfd p;
+
+  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) 
+    return MHD_NO;
+  p.fd = daemon->socket_fd;
+  p.events = POLLIN;
+  p.revents = 0;
+
+  if (poll(&p, 1, 0) < 0) {
+    if (errno == EINTR)
+      return MHD_YES;
+#if HAVE_MESSAGES
+    MHD_DLOG (daemon, "poll failed: %s\n", STRERROR (errno));
+#endif
+    return MHD_NO;
+  }
+  /* handle shutdown cases */
+  if (daemon->shutdown == MHD_YES) 
+    return MHD_NO;  
+  if (daemon->socket_fd < 0) 
+    return MHD_YES; 
+  if (0 != (p.revents & POLLIN)) 
+    MHD_accept_connection (daemon);
+  return MHD_YES;
+}
+
+/**
  * Run webserver operations (without blocking unless
  * in client callbacks).  This method should be called
  * by clients in combination with MHD_get_fdset
@@ -1017,7 +1088,10 @@
   struct MHD_Daemon *daemon = cls;
   while (daemon->shutdown == MHD_NO)
     {
-      MHD_select (daemon, MHD_YES);
+      if ((daemon->options & MHD_USE_POLL) == 0) 
+       MHD_select (daemon, MHD_YES);
+      else 
+       MHD_poll(daemon);      
       MHD_cleanup_connections (daemon);
     }
   return NULL;
@@ -1206,6 +1280,17 @@
         }
     }
 
+  /* poll support currently only works with MHD_USE_THREAD_PER_CONNECTION */
+  if ( (0 != (options & MHD_USE_POLL)) && 
+       (0 == (options & MHD_USE_THREAD_PER_CONNECTION)) ) {
+#if HAVE_MESSAGES
+      fprintf (stderr,
+               "MHD poll support only works with 
MHD_USE_THREAD_PER_CONNECTION\n");
+#endif
+      free (retVal);
+      return NULL;
+  }
+
   /* Thread pooling currently works only with internal select thread model */
   if ((0 == (options & MHD_USE_SELECT_INTERNALLY))
       && (retVal->worker_pool_size > 0))
@@ -1253,7 +1338,8 @@
       return NULL;
     }
 #ifndef WINDOWS
-  if (socket_fd >= FD_SETSIZE)
+  if ( (socket_fd >= FD_SETSIZE) &&
+       (0 == (options & MHD_USE_POLL)) )
     {
 #if HAVE_MESSAGES
       if ((options & MHD_USE_DEBUG) != 0)

Modified: libmicrohttpd/src/daemon/internal.h
===================================================================
--- libmicrohttpd/src/daemon/internal.h 2009-11-10 22:21:57 UTC (rev 9462)
+++ libmicrohttpd/src/daemon/internal.h 2009-11-11 11:55:34 UTC (rev 9463)
@@ -49,9 +49,51 @@
  * Error handler
  */
 extern MHD_PanicCallback mhd_panic;
+
+/**
+ * Closure argument for "mhd_panic".
+ */
 extern void *mhd_panic_cls;
 
+/**
+ * Events we care about with respect to poll/select
+ * for file descriptors.
+ */
+enum MHD_PollActions
+  {
+    /**
+     * No event interests us.
+     */
+    MHD_POLL_ACTION_NOTHING = 0,
 
+    /**
+     * We would like to read.
+     */
+    MHD_POLL_ACTION_IN = 1,
+
+    /**
+     * We would like to write.
+     */ 
+    MHD_POLL_ACTION_OUT = 2
+  };
+
+
+/**
+ * Socket descriptor and events we care about.
+ */
+struct MHD_Pollfd {
+  /**
+   * Socket descriptor.
+   */
+  int fd;
+
+  /**
+   * Which events do we care about for this socket?
+   */
+  enum MHD_PollActions events;
+};
+
+
 #if HAVE_MESSAGES
 /**
  * fprintf-like helper function for logging debug

Modified: libmicrohttpd/src/include/microhttpd.h
===================================================================
--- libmicrohttpd/src/include/microhttpd.h      2009-11-10 22:21:57 UTC (rev 
9462)
+++ libmicrohttpd/src/include/microhttpd.h      2009-11-11 11:55:34 UTC (rev 
9463)
@@ -292,7 +292,14 @@
    * recommended to turn this ON if you are testing clients against
    * MHD, and OFF in production.
    */
-  MHD_USE_PEDANTIC_CHECKS = 32
+  MHD_USE_PEDANTIC_CHECKS = 32,
+
+  /**
+   * Use poll instead of select. This allows sockets with fd >= FD_SETSIZE.
+   * This option only works in conjunction with MHD_USE_THREAD_PER_CONNECTION
+   * (at this point).
+   */
+  MHD_USE_POLL = 64
 };
 
 /**





reply via email to

[Prev in Thread] Current Thread [Next in Thread]