[Top][All Lists]
[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
};
/**
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r9463 - in libmicrohttpd: . doc src/daemon src/include,
gnunet <=