[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r28204 - in libmicrohttpd: . src/examples src/include src/m
From: |
gnunet |
Subject: |
[GNUnet-SVN] r28204 - in libmicrohttpd: . src/examples src/include src/microhttpd |
Date: |
Fri, 19 Jul 2013 17:51:45 +0200 |
Author: grothoff
Date: 2013-07-19 17:51:45 +0200 (Fri, 19 Jul 2013)
New Revision: 28204
Modified:
libmicrohttpd/ChangeLog
libmicrohttpd/src/examples/benchmark.c
libmicrohttpd/src/include/microhttpd.h
libmicrohttpd/src/microhttpd/connection.c
libmicrohttpd/src/microhttpd/daemon.c
libmicrohttpd/src/microhttpd/internal.h
Log:
adding experimental turbo mode
Modified: libmicrohttpd/ChangeLog
===================================================================
--- libmicrohttpd/ChangeLog 2013-07-19 15:08:58 UTC (rev 28203)
+++ libmicrohttpd/ChangeLog 2013-07-19 15:51:45 UTC (rev 28204)
@@ -1,6 +1,7 @@
Fri Jul 19 09:57:27 CEST 2013
Fix issue where connections were not cleaned up when
- 'MHD_run_from_select' was used.
+ 'MHD_run_from_select' was used. Adding experimental
+ TURBO mode.
Releasing libmicrohttpd 0.9.28. -CG
Sun Jul 14 19:57:56 CEST 2013
Modified: libmicrohttpd/src/examples/benchmark.c
===================================================================
--- libmicrohttpd/src/examples/benchmark.c 2013-07-19 15:08:58 UTC (rev
28203)
+++ libmicrohttpd/src/examples/benchmark.c 2013-07-19 15:51:45 UTC (rev
28204)
@@ -122,10 +122,12 @@
response = MHD_create_response_from_buffer (strlen (PAGE),
(void *) PAGE,
MHD_RESPMEM_PERSISTENT);
-
- d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY
-#if ! EPOLL_SUPPORT
- | MHD_USE_EPOLL_LINUX_ONLY
+ (void) MHD_add_response_header (response,
+ MHD_HTTP_HEADER_CONNECTION,
+ "close");
+ d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_SUPPRESS_DATE_NO_CLOCK
+#if EPOLL_SUPPORT
+ | MHD_USE_EPOLL_LINUX_ONLY | MHD_USE_EPOLL_TURBO
#endif
,
atoi (argv[1]),
@@ -134,6 +136,7 @@
MHD_OPTION_THREAD_POOL_SIZE, (unsigned int)
NUMBER_OF_THREADS,
MHD_OPTION_URI_LOG_CALLBACK, &uri_logger_cb, NULL,
MHD_OPTION_NOTIFY_COMPLETED, &completed_callback, NULL,
+ MHD_OPTION_CONNECTION_LIMIT, (unsigned int) 1000,
MHD_OPTION_END);
if (d == NULL)
return 1;
Modified: libmicrohttpd/src/include/microhttpd.h
===================================================================
--- libmicrohttpd/src/include/microhttpd.h 2013-07-19 15:08:58 UTC (rev
28203)
+++ libmicrohttpd/src/include/microhttpd.h 2013-07-19 15:51:45 UTC (rev
28204)
@@ -436,8 +436,14 @@
/**
* Use a single socket for IPv4 and IPv6.
*/
- MHD_USE_DUAL_STACK = MHD_USE_IPv6 | 2048
+ MHD_USE_DUAL_STACK = MHD_USE_IPv6 | 2048,
+ /**
+ * Enable EPOLL turbo. Only useful with MHD_USE_EPOLL_LINUX_ONLY.
+ * Highly experimental, do not use in production yet.
+ */
+ MHD_USE_EPOLL_TURBO = 4096
+
};
Modified: libmicrohttpd/src/microhttpd/connection.c
===================================================================
--- libmicrohttpd/src/microhttpd/connection.c 2013-07-19 15:08:58 UTC (rev
28203)
+++ libmicrohttpd/src/microhttpd/connection.c 2013-07-19 15:51:45 UTC (rev
28204)
@@ -1,6 +1,6 @@
/*
This file is part of libmicrohttpd
- (C) 2007, 2008, 2009, 2010, 2011, 2012 Daniel Pittman and Christian
Grothoff
+ (C) 2007-2013 Daniel Pittman and Christian Grothoff
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -266,8 +266,9 @@
struct MHD_Daemon *daemon;
daemon = connection->daemon;
- SHUTDOWN (connection->socket_fd,
- (MHD_YES == connection->read_closed) ? SHUT_WR : SHUT_RDWR);
+ if (0 == (connection->daemon->options & MHD_USE_EPOLL_TURBO))
+ SHUTDOWN (connection->socket_fd,
+ (MHD_YES == connection->read_closed) ? SHUT_WR : SHUT_RDWR);
connection->state = MHD_CONNECTION_CLOSED;
connection->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP;
if ( (NULL != daemon->notify_completed) &&
@@ -1485,7 +1486,7 @@
if (bytes_read < 0)
{
if ((EINTR == errno) || (EAGAIN == errno))
- return MHD_NO;
+ return MHD_NO;
#if HAVE_MESSAGES
#if HTTPS_SUPPORT
if (0 != (connection->daemon->options & MHD_USE_SSL))
@@ -2032,6 +2033,7 @@
int rend;
char *line;
+ connection->in_idle = MHD_YES;
while (1)
{
#if DEBUG_STATES
@@ -2376,32 +2378,7 @@
}
continue;
case MHD_CONNECTION_CLOSED:
- if (connection->response != NULL)
- {
- MHD_destroy_response (connection->response);
- connection->response = NULL;
- }
- if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
- (0 != pthread_mutex_lock (&daemon->cleanup_connection_mutex)) )
- MHD_PANIC ("Failed to acquire cleanup mutex\n");
- if (connection->connection_timeout == daemon->connection_timeout)
- XDLL_remove (daemon->normal_timeout_head,
- daemon->normal_timeout_tail,
- connection);
- else
- XDLL_remove (daemon->manual_timeout_head,
- daemon->manual_timeout_tail,
- connection);
- DLL_remove (daemon->connections_head,
- daemon->connections_tail,
- connection);
- DLL_insert (daemon->cleanup_head,
- daemon->cleanup_tail,
- connection);
- if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
- (0 != pthread_mutex_unlock(&daemon->cleanup_connection_mutex)) )
- MHD_PANIC ("Failed to release cleanup mutex\n");
- return MHD_NO;
+ goto cleanup_connection;
default:
EXTRA_CHECK (0);
break;
@@ -2413,35 +2390,109 @@
(timeout <= (MHD_monotonic_time() - connection->last_activity)) )
{
MHD_connection_close (connection,
MHD_REQUEST_TERMINATED_TIMEOUT_REACHED);
+ connection->in_idle = MHD_NO;
return MHD_YES;
}
MHD_connection_update_event_loop_info (connection);
switch (connection->event_loop_info)
{
case MHD_EVENT_LOOP_INFO_READ:
- if (0 != (connection->epoll_state & MHD_EPOLL_STATE_READ_READY))
- EDLL_insert (daemon->eready_head,
- daemon->eready_tail,
- connection);
+ if ( (0 != (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) &&
+ (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL)) )
+ {
+ EDLL_insert (daemon->eready_head,
+ daemon->eready_tail,
+ connection);
+ connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
+ }
break;
case MHD_EVENT_LOOP_INFO_WRITE:
- if (0 != (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY))
- EDLL_insert (daemon->eready_head,
- daemon->eready_tail,
- connection);
+ if ( (0 != (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY)) &&
+ (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL)) )
+ {
+ EDLL_insert (daemon->eready_head,
+ daemon->eready_tail,
+ connection);
+ connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
+ }
break;
case MHD_EVENT_LOOP_INFO_BLOCK:
/* we should look at this connection again in the next iteration
of the event loop, as we're waiting on the application */
- EDLL_insert (daemon->eready_head,
- daemon->eready_tail,
- connection);
+ if (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
+ {
+ EDLL_insert (daemon->eready_head,
+ daemon->eready_tail,
+ connection);
+ connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
+ }
break;
case MHD_EVENT_LOOP_INFO_CLEANUP:
/* This connection is finished, nothing left to do */
break;
}
+
+#if EPOLL_SUPPORT
+ if ( (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY)) &&
+ (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) &&
+ ( (0 == (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY)) ||
+ ( (0 == (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) &&
+ (MHD_EVENT_LOOP_INFO_READ == connection->event_loop_info) &&
+ (MHD_NO == connection->read_closed) ) ) )
+ {
+ /* add to epoll set */
+ struct epoll_event event;
+
+ event.events = EPOLLIN | EPOLLOUT | EPOLLET;
+ event.data.ptr = connection;
+ if (0 != epoll_ctl (daemon->epoll_fd,
+ EPOLL_CTL_ADD,
+ connection->socket_fd,
+ &event))
+ {
+#if HAVE_MESSAGES
+ if (0 != (daemon->options & MHD_USE_DEBUG))
+ MHD_DLOG (daemon,
+ "Call to epoll_ctl failed: %s\n",
+ STRERROR (errno));
+#endif
+ connection->state = MHD_CONNECTION_CLOSED;
+ goto cleanup_connection;
+ }
+ connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
+ }
+#endif
+ connection->in_idle = MHD_NO;
return MHD_YES;
+
+ cleanup_connection:
+ if (NULL != connection->response)
+ {
+ MHD_destroy_response (connection->response);
+ connection->response = NULL;
+ }
+ if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
+ (0 != pthread_mutex_lock (&daemon->cleanup_connection_mutex)) )
+ MHD_PANIC ("Failed to acquire cleanup mutex\n");
+ if (connection->connection_timeout == daemon->connection_timeout)
+ XDLL_remove (daemon->normal_timeout_head,
+ daemon->normal_timeout_tail,
+ connection);
+ else
+ XDLL_remove (daemon->manual_timeout_head,
+ daemon->manual_timeout_tail,
+ connection);
+ DLL_remove (daemon->connections_head,
+ daemon->connections_tail,
+ connection);
+ DLL_insert (daemon->cleanup_head,
+ daemon->cleanup_tail,
+ connection);
+ if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
+ (0 != pthread_mutex_unlock(&daemon->cleanup_connection_mutex)) )
+ MHD_PANIC ("Failed to release cleanup mutex\n");
+ connection->in_idle = MHD_NO;
+ return MHD_NO;
}
@@ -2589,11 +2640,13 @@
/* response was queued "early",
refuse to read body / footers or further
requests! */
- (void) SHUTDOWN (connection->socket_fd, SHUT_RD);
+ if (0 == (connection->daemon->options & MHD_USE_EPOLL_TURBO))
+ (void) SHUTDOWN (connection->socket_fd, SHUT_RD);
connection->read_closed = MHD_YES;
connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
}
- (void) MHD_connection_handle_idle (connection);
+ if (MHD_NO == connection->in_idle)
+ (void) MHD_connection_handle_idle (connection);
return MHD_YES;
}
Modified: libmicrohttpd/src/microhttpd/daemon.c
===================================================================
--- libmicrohttpd/src/microhttpd/daemon.c 2013-07-19 15:08:58 UTC (rev
28203)
+++ libmicrohttpd/src/microhttpd/daemon.c 2013-07-19 15:51:45 UTC (rev
28204)
@@ -809,7 +809,7 @@
}
ret = RECV (connection->socket_fd, other, i, MSG_NOSIGNAL);
#if EPOLL_SUPPORT
- if (ret < i)
+ if (ret < (ssize_t) i)
{
/* partial read --- no longer read-ready */
connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
@@ -884,7 +884,7 @@
#endif
ret = SEND (connection->socket_fd, other, i, MSG_NOSIGNAL);
#if EPOLL_SUPPORT
- if (ret < i)
+ if (ret < (ssize_t) i)
{
/* partial write --- no longer write-ready */
connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
@@ -1121,37 +1121,43 @@
MHD_set_http_callbacks_ (connection);
connection->recv_cls = &recv_param_adapter;
connection->send_cls = &send_param_adapter;
- /* non-blocking sockets are required on most systems and for GNUtls;
- however, they somehow cause serious problems on CYGWIN (#1824) */
+
+ if (0 == (connection->daemon->options & MHD_USE_EPOLL_TURBO))
+ {
+ /* non-blocking sockets are required on most systems and for GNUtls;
+ however, they somehow cause serious problems on CYGWIN (#1824);
+ in turbo mode, we assume that non-blocking was already set
+ by 'accept4' or whoever calls 'MHD_add_connection' */
#ifdef CYGWIN
- if (0 != (daemon->options & MHD_USE_SSL))
+ if (0 != (daemon->options & MHD_USE_SSL))
#endif
- {
- /* make socket non-blocking */
+ {
+ /* make socket non-blocking */
#ifndef MINGW
- int flags = fcntl (connection->socket_fd, F_GETFL);
- if ( (-1 == flags) ||
- (0 != fcntl (connection->socket_fd, F_SETFL, flags | O_NONBLOCK)) )
- {
+ int flags = fcntl (connection->socket_fd, F_GETFL);
+ if ( (-1 == flags) ||
+ (0 != fcntl (connection->socket_fd, F_SETFL, flags |
O_NONBLOCK)) )
+ {
#if HAVE_MESSAGES
- MHD_DLOG (daemon,
- "Failed to make socket %d non-blocking: %s\n",
- connection->socket_fd,
- STRERROR (errno));
+ MHD_DLOG (daemon,
+ "Failed to make socket %d non-blocking: %s\n",
+ connection->socket_fd,
+ STRERROR (errno));
#endif
- }
+ }
#else
- unsigned long flags = 1;
- if (0 != ioctlsocket (connection->socket_fd, FIONBIO, &flags))
- {
+ unsigned long flags = 1;
+ if (0 != ioctlsocket (connection->socket_fd, FIONBIO, &flags))
+ {
#if HAVE_MESSAGES
- MHD_DLOG (daemon,
- "Failed to make socket non-blocking: %s\n",
- STRERROR (errno));
+ MHD_DLOG (daemon,
+ "Failed to make socket non-blocking: %s\n",
+ STRERROR (errno));
#endif
- }
+ }
#endif
- }
+ }
+ }
#if HTTPS_SUPPORT
if (0 != (daemon->options & MHD_USE_SSL))
@@ -1228,25 +1234,35 @@
#if EPOLL_SUPPORT
if (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY))
{
- struct epoll_event event;
-
- event.events = EPOLLIN | EPOLLOUT | EPOLLET;
- event.data.ptr = connection;
- if (0 != epoll_ctl (daemon->epoll_fd,
- EPOLL_CTL_ADD,
- client_socket,
- &event))
+ if (0 == (daemon->options & MHD_USE_EPOLL_TURBO))
{
+ struct epoll_event event;
+
+ event.events = EPOLLIN | EPOLLOUT | EPOLLET;
+ event.data.ptr = connection;
+ if (0 != epoll_ctl (daemon->epoll_fd,
+ EPOLL_CTL_ADD,
+ client_socket,
+ &event))
+ {
#if HAVE_MESSAGES
- if (0 != (daemon->options & MHD_USE_DEBUG))
- MHD_DLOG (daemon,
- "Call to epoll_ctl failed: %s\n",
- STRERROR (errno));
+ if (0 != (daemon->options & MHD_USE_DEBUG))
+ MHD_DLOG (daemon,
+ "Call to epoll_ctl failed: %s\n",
+ STRERROR (errno));
#endif
- goto cleanup;
+ goto cleanup;
+ }
+ connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
}
- daemon->listen_socket_in_epoll = MHD_YES;
-
+ else
+ {
+ connection->epoll_state |= MHD_EPOLL_STATE_READ_READY |
MHD_EPOLL_STATE_WRITE_READY
+ | MHD_EPOLL_STATE_IN_EREADY_EDLL;
+ EDLL_insert (daemon->eready_head,
+ daemon->eready_tail,
+ connection);
+ }
}
#endif
daemon->max_connections--;
@@ -1300,13 +1316,19 @@
socklen_t addrlen;
int s;
int fd;
+ int nonblock;
addrlen = sizeof (addrstorage);
memset (addr, 0, sizeof (addrstorage));
if (-1 == (fd = daemon->socket_fd))
return MHD_NO;
+ nonblock = SOCK_NONBLOCK;
+#ifdef CYGWIN
+ if (0 == (daemon->options & MHD_USE_SSL))
+ nonblock = 0;
+#endif
#if HAVE_ACCEPT4
- s = accept4 (fd, addr, &addrlen, SOCK_CLOEXEC);
+ s = accept4 (fd, addr, &addrlen, SOCK_CLOEXEC | nonblock);
#else
s = ACCEPT (fd, addr, &addrlen);
#endif
@@ -1329,9 +1351,19 @@
}
#if !HAVE_ACCEPT4
{
- /* make socket non-inheritable */
+ /* make socket non-inheritable and non-blocking */
#ifdef WINDOWS
DWORD dwFlags;
+ unsigned long flags = 1;
+
+ if (0 != ioctlsocket (s, FIONBIO, &flags))
+ {
+#if HAVE_MESSAGES
+ MHD_DLOG (daemon,
+ "Failed to make socket non-blocking: %s\n",
+ STRERROR (errno));
+#endif
+ }
if (!GetHandleInformation ((HANDLE) s, &dwFlags) ||
((dwFlags != dwFlags & ~HANDLE_FLAG_INHERIT) &&
!SetHandleInformation ((HANDLE) s, HANDLE_FLAG_INHERIT, 0)))
@@ -1342,14 +1374,19 @@
"Failed to make socket non-inheritable: %s\n",
STRERROR (errno));
#endif
- }
+ }
#else
int flags;
+ nonblock = O_NONBLOCK;
+#ifdef CYGWIN
+ if (0 == (daemon->options & MHD_USE_SSL))
+ nonblock = 0;
+#endif
flags = fcntl (s, F_GETFD);
if ( ( (-1 == flags) ||
( (flags != (flags | FD_CLOEXEC)) &&
- (0 != fcntl (s, F_SETFD, flags | FD_CLOEXEC)) ) ) )
+ (0 != fcntl (s, F_SETFD, flags | nonblock | FD_CLOEXEC)) ) ) )
{
#if HAVE_MESSAGES
MHD_DLOG (daemon,
@@ -1358,7 +1395,10 @@
#endif
}
#endif
+ /* make socket non-blocking */
+
}
+
#endif
#if HAVE_MESSAGES
#if DEBUG_CONNECT
@@ -1406,10 +1446,13 @@
if (pos->tls_session != NULL)
gnutls_deinit (pos->tls_session);
#endif
- MHD_ip_limit_del (daemon, (struct sockaddr*)pos->addr, pos->addr_len);
+ MHD_ip_limit_del (daemon,
+ (struct sockaddr *) pos->addr,
+ pos->addr_len);
#if EPOLL_SUPPORT
if ( (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY)) &&
- (-1 != daemon->epoll_fd) )
+ (-1 != daemon->epoll_fd) &&
+ (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) )
{
/* epoll documentation suggests that closing a FD
automatically removes it from the epoll set; however,
@@ -1422,6 +1465,7 @@
pos->socket_fd,
NULL))
MHD_PANIC ("Failed to remove FD from epoll set\n");
+ pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET;
}
#endif
if (NULL != pos->response)
@@ -1949,10 +1993,10 @@
/**
* Do 'epoll'-based processing (this function is allowed to
- * block).
+ * block if 'may_block' is set to MHD_YES).
*
* @param daemon daemon to run poll loop for
- * @param may_block YES if blocking, NO if non-blocking
+ * @param may_block MHD_YES if blocking, MHD_NO if non-blocking
* @return MHD_NO on serious errors, MHD_YES on success
*/
static int
@@ -1966,7 +2010,8 @@
int timeout_ms;
MHD_UNSIGNED_LONG_LONG timeout_ll;
int num_events;
- unsigned int i;
+ unsigned int i;
+ unsigned int series_length;
if (-1 == daemon->epoll_fd)
return MHD_NO; /* we're down! */
@@ -2082,8 +2127,11 @@
{
/* run 'accept' until it fails or we are not allowed to take
on more connections */
+ series_length = 0;
while ( (MHD_YES == MHD_accept_connection (daemon)) &&
- (0 != daemon->max_connections) ) ;
+ (0 != daemon->max_connections) &&
+ (series_length < 128) )
+ series_length++;
}
}
}
@@ -2094,7 +2142,7 @@
EDLL_remove (daemon->eready_head,
daemon->eready_tail,
pos);
- pos->epoll_state -= MHD_EPOLL_STATE_IN_EREADY_EDLL;
+ pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
if (MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info)
pos->read_handler (pos);
if (MHD_EVENT_LOOP_INFO_WRITE == pos->event_loop_info)
Modified: libmicrohttpd/src/microhttpd/internal.h
===================================================================
--- libmicrohttpd/src/microhttpd/internal.h 2013-07-19 15:08:58 UTC (rev
28203)
+++ libmicrohttpd/src/microhttpd/internal.h 2013-07-19 15:51:45 UTC (rev
28204)
@@ -111,8 +111,13 @@
/**
* Is this connection currently in the 'eready' EDLL?
*/
- MHD_EPOLL_STATE_IN_EREADY_EDLL = 4
+ MHD_EPOLL_STATE_IN_EREADY_EDLL = 4,
+ /**
+ * Is this connection currently in the 'epoll' set?
+ */
+ MHD_EPOLL_STATE_IN_EPOLL_SET = 8
+
};
@@ -719,6 +724,11 @@
*/
int thread_joined;
+ /**
+ * Are we currently inside the "idle" handler (to avoid recursively invoking
it).
+ */
+ int in_idle;
+
#if EPOLL_SUPPORT
/**
* What is the state of this socket in relation to epoll?
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r28204 - in libmicrohttpd: . src/examples src/include src/microhttpd,
gnunet <=