[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r14556 - in libmicrohttpd: . src/daemon src/examples src/in
From: |
gnunet |
Subject: |
[GNUnet-SVN] r14556 - in libmicrohttpd: . src/daemon src/examples src/include |
Date: |
Tue, 1 Mar 2011 16:09:14 +0100 |
Author: grothoff
Date: 2011-03-01 16:09:14 +0100 (Tue, 01 Mar 2011)
New Revision: 14556
Modified:
libmicrohttpd/ChangeLog
libmicrohttpd/src/daemon/daemon.c
libmicrohttpd/src/daemon/internal.h
libmicrohttpd/src/examples/minimal_example.c
libmicrohttpd/src/include/microhttpd.h
Log:
enable poll more broadly, fix timeout, use pipe instead of signal
Modified: libmicrohttpd/ChangeLog
===================================================================
--- libmicrohttpd/ChangeLog 2011-03-01 15:08:50 UTC (rev 14555)
+++ libmicrohttpd/ChangeLog 2011-03-01 15:09:14 UTC (rev 14556)
@@ -1,3 +1,8 @@
+Tue Mar 1 13:58:04 CET 2011
+ Allow use of 'poll' in combination with the external select mode.
+ Avoid using pthread signals (SIGALRM), use pipe instead.
+ Corrected timeout calculation (s vs. ms). -CG
+
Wed Feb 23 14:21:44 CET 2011
Removing useless code pointed out by Eivind Sarto. -CG
Modified: libmicrohttpd/src/daemon/daemon.c
===================================================================
--- libmicrohttpd/src/daemon/daemon.c 2011-03-01 15:08:50 UTC (rev 14555)
+++ libmicrohttpd/src/daemon/daemon.c 2011-03-01 15:09:14 UTC (rev 14556)
@@ -80,14 +80,6 @@
#endif
#endif
-#ifdef __SYMBIAN32__
-static void pthread_kill (int, int) {
- // Symbian doesn't have signals. The user of the library is required to
- // run it in an external select loop.
- abort();
-}
-#endif // __SYMBIAN32__
-
/**
* Default implementation of the panic function
*/
@@ -572,45 +564,54 @@
fd_set es;
int max;
struct timeval tv;
+ struct timeval *tvp;
unsigned int timeout;
+ time_t now;
#ifdef HAVE_POLL_H
struct MHD_Pollfd mp;
- struct pollfd p;
+ struct pollfd p[2];
#endif
timeout = con->daemon->connection_timeout;
while ((!con->daemon->shutdown) && (con->socket_fd != -1)) {
- tv.tv_usec = 0;
- if ( (timeout > (time (NULL) - con->last_activity)) ||
- (timeout == 0) )
+ tvp = NULL;
+ if (timeout > 0)
{
- /* in case we are missing the SIGALRM, keep going after
- at most 1s; see
http://lists.gnu.org/archive/html/libmicrohttpd/2009-10/msg00013.html */
- tv.tv_sec = 1;
- if ((con->state == MHD_CONNECTION_NORMAL_BODY_UNREADY) ||
- (con->state == MHD_CONNECTION_CHUNKED_BODY_UNREADY))
- {
- /* do not block (we're waiting for our callback to succeed) */
- tv.tv_sec = 0;
- }
+ now = time (NULL);
+ if (now - con->last_activity > timeout)
+ tv.tv_sec = 0;
+ else
+ tv.tv_sec = timeout - (now - con->last_activity);
+ tvp = &tv;
}
- else
+ if ((con->state == MHD_CONNECTION_NORMAL_BODY_UNREADY) ||
+ (con->state == MHD_CONNECTION_CHUNKED_BODY_UNREADY))
{
+ /* do not block (we're waiting for our callback to succeed) */
tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ tvp = &tv;
}
#ifdef HAVE_POLL_H
- if (0 == (con->daemon->options & MHD_USE_POLL)) {
+ if (0 == (con->daemon->options & MHD_USE_POLL))
+ {
#else
- {
+ {
#endif
- /* 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) {
+ /* use select */
+ FD_ZERO (&rs);
+ FD_ZERO (&ws);
+ FD_ZERO (&es);
+ if (-1 != con->daemon->wpipe[0])
+ {
+ max = con->daemon->wpipe[0];
+ FD_SET (con->daemon->wpipe[0], &rs);
+ }
+ else
+ max = 0;
+ MHD_connection_get_fdset (con, &rs, &ws, &es, &max);
+ num_ready = SELECT (max + 1, &rs, &ws, &es, tvp);
+ if (num_ready < 0) {
if (errno == EINTR)
continue;
#if HAVE_MESSAGES
@@ -618,52 +619,54 @@
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);
- }
+ }
+ /* 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);
+ }
#ifdef HAVE_POLL_H
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;
+ {
+ /* use poll */
+ memset(&mp, 0, sizeof (struct MHD_Pollfd));
+ MHD_connection_get_pollfd(con, &mp);
+ memset(&p, 0, sizeof (p));
+ p[0].fd = mp.fd;
+ if (mp.events & MHD_POLL_ACTION_IN)
+ p[0].events |= POLLIN;
+ if (mp.events & MHD_POLL_ACTION_OUT)
+ p[0].events |= POLLOUT;
+ p[1].fd = con->daemon->wpipe[0];
+ p[1].events |= POLLIN;
+
+ if (poll (p, 2, (tvp == NULL) ? -1 : (tv.tv_sec * 1000)) < 0)
+ {
+ if (errno == EINTR)
+ continue;
#if HAVE_MESSAGES
- MHD_DLOG (con->daemon, "Error during poll: `%s'\n",
- STRERROR (errno));
+ MHD_DLOG (con->daemon, "Error during poll: `%s'\n",
+ STRERROR (errno));
#endif
- break;
- }
- 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);
+ break;
+ }
+ if ( (con->socket_fd != -1) &&
+ (0 != (p[0].revents & POLLIN)) )
+ con->read_handler (con);
+ if ( (con->socket_fd != -1) &&
+ (0 != (p[0].revents & POLLOUT)) )
+ con->write_handler (con);
+ if (con->socket_fd != -1)
+ con->idle_handler (con);
+ if ( (con->socket_fd != -1) &&
+ (0 != (p[0].revents & (POLLERR | POLLHUP))) )
+ MHD_connection_close (con, MHD_REQUEST_TERMINATED_WITH_ERROR);
+ }
+#endif
}
-#endif
- }
if (con->socket_fd != -1)
{
#if DEBUG_CLOSE
@@ -1085,7 +1088,7 @@
prev->next = pos->next;
if (0 != (pos->daemon->options & MHD_USE_THREAD_PER_CONNECTION))
{
- pthread_kill (pos->pid, SIGALRM);
+
if (0 != (rc = pthread_join (pos->pid, &unused)))
{
#if HAVE_MESSAGES
@@ -1148,7 +1151,7 @@
return MHD_NO; /* no connections */
now = time (NULL);
/* start with conservative estimate */
- earliest_deadline = now + dto;
+ earliest_deadline = now + dto + 1;
while (pos != NULL)
{
if (earliest_deadline > pos->last_activity + dto)
@@ -1163,7 +1166,7 @@
if (earliest_deadline < now)
*timeout = 0;
else
- *timeout = (earliest_deadline - now);
+ *timeout = 1000 * (1 + earliest_deadline - now);
return MHD_YES;
}
@@ -1185,6 +1188,7 @@
fd_set es;
int max;
struct timeval timeout;
+ struct timeval *tv;
unsigned MHD_LONG_LONG ltimeout;
int ds;
@@ -1195,8 +1199,13 @@
FD_ZERO (&rs);
FD_ZERO (&ws);
FD_ZERO (&es);
- max = 0;
-
+ if (-1 != daemon->wpipe[0])
+ {
+ max = daemon->wpipe[0];
+ FD_SET (daemon->wpipe[0], &rs);
+ }
+ else
+ max = 0;
if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
{
/* single-threaded, go over everything */
@@ -1217,26 +1226,21 @@
FD_SET (max, &rs);
}
- /* in case we are missing the SIGALRM, keep going after
- at most 1s; see
http://lists.gnu.org/archive/html/libmicrohttpd/2009-10/msg00013.html */
- timeout.tv_usec = 0;
- timeout.tv_sec = 1;
+ tv = NULL;
if (may_block == MHD_NO)
{
timeout.tv_usec = 0;
timeout.tv_sec = 0;
+ tv = &timeout;
}
- else
+ else if (MHD_YES == MHD_get_timeout (daemon, <imeout))
{
/* ltimeout is in ms */
- if ( (MHD_YES == MHD_get_timeout (daemon, <imeout)) &&
- (ltimeout < 1000) )
- {
- timeout.tv_usec = ltimeout * 1000;
- timeout.tv_sec = 0;
- }
+ timeout.tv_usec = (ltimeout % 1000) * 1000;
+ timeout.tv_sec = ltimeout / 1000;
+ tv = &timeout;
}
- num_ready = SELECT (max + 1, &rs, &ws, &es, &timeout);
+ num_ready = SELECT (max + 1, &rs, &ws, &es, tv);
if (daemon->shutdown == MHD_YES)
return MHD_NO;
@@ -1279,38 +1283,93 @@
return MHD_YES;
}
+
/**
- * Poll for new connection. Used only with THREAD_PER_CONNECTION
+ * Poll for new connection.
*
* @param daemon daemon to run poll loop for
+ * @param may_block YES if blocking, NO if non-blocking
+ * @return MHD_NO on serious errors, MHD_YES on success
*/
static int
-MHD_poll (struct MHD_Daemon *daemon)
+MHD_poll (struct MHD_Daemon *daemon,
+ int may_block)
{
#ifdef HAVE_POLL_H
- struct pollfd p;
+ unsigned int num_connections;
+ struct MHD_Connection *pos;
- 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, 1000) < 0) {
- if (errno == EINTR)
- return MHD_YES;
+ num_connections = 0;
+ pos = daemon->connections;
+ while (pos != NULL)
+ {
+ num_connections++;
+ pos = pos->next;
+ }
+ {
+ struct pollfd p[2 + num_connections];
+ struct MHD_Pollfd mp;
+ unsigned MHD_LONG_LONG ltimeout;
+ unsigned int i;
+ int timeout;
+
+ p[0].fd = daemon->socket_fd;
+ p[0].events = POLLIN;
+ p[0].revents = 0;
+ p[1].fd = daemon->wpipe[0];
+ p[1].events = POLLIN;
+ p[1].revents = 0;
+ if (may_block == MHD_NO)
+ timeout = 0;
+ else if (MHD_YES != MHD_get_timeout (daemon, <imeout))
+ timeout = -1;
+ else
+ timeout = (ltimeout > INT_MAX) ? INT_MAX : (int) ltimeout;
+
+ i = 0;
+ pos = daemon->connections;
+ while (pos != NULL)
+ {
+ memset(&mp, 0, sizeof (struct MHD_Pollfd));
+ MHD_connection_get_pollfd (pos, &mp);
+ memset(&p, 0, sizeof (p));
+ p[2+i].fd = mp.fd;
+ if (mp.events & MHD_POLL_ACTION_IN)
+ p[2+i].events |= POLLIN;
+ if (mp.events & MHD_POLL_ACTION_OUT)
+ p[2+i].events |= POLLOUT;
+ i++;
+ pos = pos->next;
+ }
+ if (poll (p, 2 + num_connections, timeout) < 0) {
+ if (errno == EINTR)
+ return MHD_YES;
#if HAVE_MESSAGES
- MHD_DLOG (daemon, "poll failed: %s\n", STRERROR (errno));
+ MHD_DLOG (daemon, "poll failed: %s\n", STRERROR (errno));
#endif
- return MHD_NO;
+ 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[0].revents & POLLIN))
+ MHD_accept_connection (daemon);
+ i = 0;
+ pos = daemon->connections;
+ while (pos != NULL)
+ {
+ if (0 != (p[2+i].revents & POLLIN))
+ pos->read_handler (pos);
+ if (0 != (p[2+i].revents & POLLOUT))
+ pos->write_handler (pos);
+ if (pos->socket_fd != -1)
+ pos->idle_handler (pos);
+ i++;
+ pos = pos->next;
+ }
}
- /* 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;
#else
return MHD_NO;
@@ -1335,7 +1394,10 @@
& MHD_USE_THREAD_PER_CONNECTION))
|| (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)))
return MHD_NO;
- MHD_select (daemon, MHD_NO);
+ if ((daemon->options & MHD_USE_POLL) == 0)
+ MHD_select (daemon, MHD_NO);
+ else
+ MHD_poll (daemon, MHD_NO);
MHD_cleanup_connections (daemon);
return MHD_YES;
}
@@ -1357,7 +1419,7 @@
if ((daemon->options & MHD_USE_POLL) == 0)
MHD_select (daemon, MHD_YES);
else
- MHD_poll(daemon);
+ MHD_poll (daemon, MHD_YES);
MHD_cleanup_connections (daemon);
}
return NULL;
@@ -1725,7 +1787,7 @@
}
#endif
retVal->socket_fd = -1;
- retVal->options = (enum MHD_OPTION)options;
+ retVal->options = (enum MHD_OPTION) options;
retVal->port = port;
retVal->apc = apc;
retVal->apc_cls = apc_cls;
@@ -1735,6 +1797,37 @@
retVal->pool_size = MHD_POOL_SIZE_DEFAULT;
retVal->unescape_callback = &MHD_http_unescape;
retVal->connection_timeout = 0; /* no timeout */
+ retVal->wpipe[0] = -1;
+ retVal->wpipe[1] = -1;
+ if ( (0 != (options & MHD_USE_THREAD_PER_CONNECTION)) ||
+ (0 != (options & MHD_USE_SELECT_INTERNALLY)) )
+ {
+ if (0 != pipe (retVal->wpipe))
+ {
+#if HAVE_MESSAGES
+ FPRINTF(stderr,
+ "Failed to create control pipe: %s\n",
+ STRERROR (errno));
+#endif
+ free (retVal);
+ return NULL;
+ }
+#ifndef WINDOWS
+ if ( (0 == (options & MHD_USE_POLL)) &&
+ (retVal->wpipe[0] >= FD_SETSIZE) )
+ {
+#if HAVE_MESSAGES
+ FPRINTF(stderr,
+ "file descriptor for control pipe exceeds maximum value\n");
+#endif
+ close (retVal->wpipe[0]);
+ close (retVal->wpipe[1]);
+ free (retVal);
+ return NULL;
+ }
+#endif
+ }
+
#ifdef DAUTH_SUPPORT
retVal->digest_auth_rand_size = 0;
retVal->digest_auth_random = NULL;
@@ -1809,22 +1902,6 @@
}
#endif
- /* 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
- MHD_DLOG (retVal,
- "MHD poll support only works with
MHD_USE_THREAD_PER_CONNECTION\n");
-#endif
-#if DAUTH_SUPPORT
- free (retVal->nnc);
- pthread_mutex_destroy (&retVal->nnc_lock);
-#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) )
@@ -2172,12 +2249,15 @@
int fd;
unsigned int i;
int rc;
+ char c;
if (daemon == NULL)
return;
daemon->shutdown = MHD_YES;
fd = daemon->socket_fd;
daemon->socket_fd = -1;
+ if (daemon->wpipe[1] != -1)
+ write (daemon->wpipe[1], "e", 1);
/* Prepare workers for shutdown */
for (i = 0; i < daemon->worker_pool_size; ++i)
@@ -2202,8 +2282,6 @@
/* Signal workers to stop and clean them up */
for (i = 0; i < daemon->worker_pool_size; ++i)
- pthread_kill (daemon->worker_pool[i].pid, SIGALRM);
- for (i = 0; i < daemon->worker_pool_size; ++i)
{
if (0 != (rc = pthread_join (daemon->worker_pool[i].pid, &unused)))
{
@@ -2221,7 +2299,6 @@
((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY))
&& (0 == daemon->worker_pool_size)))
{
- pthread_kill (daemon->pid, SIGALRM);
if (0 != (rc = pthread_join (daemon->pid, &unused)))
{
#if HAVE_MESSAGES
@@ -2272,6 +2349,15 @@
pthread_mutex_destroy (&daemon->nnc_lock);
#endif
pthread_mutex_destroy (&daemon->per_ip_connection_mutex);
+
+ if (daemon->wpipe[1] != -1)
+ {
+ /* just to be sure, remove the one char we
+ wrote into the pipe */
+ (void) read (daemon->wpipe[0], &c, 1);
+ close (daemon->wpipe[0]);
+ close (daemon->wpipe[1]);
+ }
free (daemon);
}
@@ -2330,18 +2416,6 @@
return PACKAGE_VERSION;
}
-#ifndef WINDOWS
-
-static struct sigaction sig;
-
-static struct sigaction old;
-
-static void
-sigalrmHandler (int sig)
-{
-}
-#endif
-
#ifdef __GNUC__
#define ATTRIBUTE_CONSTRUCTOR __attribute__ ((constructor))
#define ATTRIBUTE_DESTRUCTOR __attribute__ ((destructor))
@@ -2355,22 +2429,14 @@
#endif
/**
- * Initialize the signal handler for SIGALRM
- * and do other setup work.
+ * Initialize do setup work.
*/
void ATTRIBUTE_CONSTRUCTOR MHD_init ()
{
mhd_panic = &mhd_panic_std;
mhd_panic_cls = NULL;
-#ifndef WINDOWS
- /* make sure SIGALRM does not kill us */
- memset (&sig, 0, sizeof (struct sigaction));
- memset (&old, 0, sizeof (struct sigaction));
- sig.sa_flags = SA_NODEFER;
- sig.sa_handler = &sigalrmHandler;
- sigaction (SIGALRM, &sig, &old);
-#else
+#ifdef WINDOWS
plibc_init ("GNU", "libmicrohttpd");
#endif
#if HTTPS_SUPPORT
@@ -2388,9 +2454,7 @@
if (0 != pthread_mutex_destroy(&MHD_gnutls_init_mutex))
mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
#endif
-#ifndef WINDOWS
- sigaction (SIGALRM, &old, &sig);
-#else
+#ifdef WINDOWS
plibc_shutdown ();
#endif
}
Modified: libmicrohttpd/src/daemon/internal.h
===================================================================
--- libmicrohttpd/src/daemon/internal.h 2011-03-01 15:08:50 UTC (rev 14555)
+++ libmicrohttpd/src/daemon/internal.h 2011-03-01 15:09:14 UTC (rev 14556)
@@ -857,6 +857,11 @@
int socket_fd;
/**
+ * Pipe we use to signal shutdown.
+ */
+ int wpipe[2];
+
+ /**
* Are we shutting down?
*/
int shutdown;
Modified: libmicrohttpd/src/examples/minimal_example.c
===================================================================
--- libmicrohttpd/src/examples/minimal_example.c 2011-03-01 15:08:50 UTC
(rev 14555)
+++ libmicrohttpd/src/examples/minimal_example.c 2011-03-01 15:09:14 UTC
(rev 14556)
@@ -67,7 +67,10 @@
printf ("%s PORT\n", argv[0]);
return 1;
}
- d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG |
MHD_USE_POLL,
+ // MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+ // MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG |
MHD_USE_POLL,
+ // MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
atoi (argv[1]),
NULL, NULL, &ahc_echo, PAGE,
MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 5,
Modified: libmicrohttpd/src/include/microhttpd.h
===================================================================
--- libmicrohttpd/src/include/microhttpd.h 2011-03-01 15:08:50 UTC (rev
14555)
+++ libmicrohttpd/src/include/microhttpd.h 2011-03-01 15:09:14 UTC (rev
14556)
@@ -106,7 +106,7 @@
/**
* Current version of the library.
*/
-#define MHD_VERSION 0x00090702
+#define MHD_VERSION 0x00090703
/**
* MHD-internal return code for "YES".
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r14556 - in libmicrohttpd: . src/daemon src/examples src/include,
gnunet <=