aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2013-07-19 15:51:45 +0000
committerChristian Grothoff <christian@grothoff.org>2013-07-19 15:51:45 +0000
commit1237387390f4be97f861a5cb93eec2445fe1a565 (patch)
treec05e35d19805c6fd5aae0a85759288f44afe89e2
parent14e4efd674ad0c3a40868057fb6754727a1e7b39 (diff)
downloadlibmicrohttpd-1237387390f4be97f861a5cb93eec2445fe1a565.tar.gz
libmicrohttpd-1237387390f4be97f861a5cb93eec2445fe1a565.zip
adding experimental turbo mode
-rw-r--r--ChangeLog3
-rw-r--r--src/examples/benchmark.c11
-rw-r--r--src/include/microhttpd.h8
-rw-r--r--src/microhttpd/connection.c139
-rw-r--r--src/microhttpd/daemon.c148
-rw-r--r--src/microhttpd/internal.h12
6 files changed, 221 insertions, 100 deletions
diff --git a/ChangeLog b/ChangeLog
index 728a9f9a..58b754f0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,7 @@
1Fri Jul 19 09:57:27 CEST 2013 1Fri Jul 19 09:57:27 CEST 2013
2 Fix issue where connections were not cleaned up when 2 Fix issue where connections were not cleaned up when
3 'MHD_run_from_select' was used. 3 'MHD_run_from_select' was used. Adding experimental
4 TURBO mode.
4 Releasing libmicrohttpd 0.9.28. -CG 5 Releasing libmicrohttpd 0.9.28. -CG
5 6
6Sun Jul 14 19:57:56 CEST 2013 7Sun Jul 14 19:57:56 CEST 2013
diff --git a/src/examples/benchmark.c b/src/examples/benchmark.c
index 711d118a..48f294e0 100644
--- a/src/examples/benchmark.c
+++ b/src/examples/benchmark.c
@@ -122,10 +122,12 @@ main (int argc, char *const *argv)
122 response = MHD_create_response_from_buffer (strlen (PAGE), 122 response = MHD_create_response_from_buffer (strlen (PAGE),
123 (void *) PAGE, 123 (void *) PAGE,
124 MHD_RESPMEM_PERSISTENT); 124 MHD_RESPMEM_PERSISTENT);
125 125 (void) MHD_add_response_header (response,
126 d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY 126 MHD_HTTP_HEADER_CONNECTION,
127#if ! EPOLL_SUPPORT 127 "close");
128 | MHD_USE_EPOLL_LINUX_ONLY 128 d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_SUPPRESS_DATE_NO_CLOCK
129#if EPOLL_SUPPORT
130 | MHD_USE_EPOLL_LINUX_ONLY | MHD_USE_EPOLL_TURBO
129#endif 131#endif
130 , 132 ,
131 atoi (argv[1]), 133 atoi (argv[1]),
@@ -134,6 +136,7 @@ main (int argc, char *const *argv)
134 MHD_OPTION_THREAD_POOL_SIZE, (unsigned int) NUMBER_OF_THREADS, 136 MHD_OPTION_THREAD_POOL_SIZE, (unsigned int) NUMBER_OF_THREADS,
135 MHD_OPTION_URI_LOG_CALLBACK, &uri_logger_cb, NULL, 137 MHD_OPTION_URI_LOG_CALLBACK, &uri_logger_cb, NULL,
136 MHD_OPTION_NOTIFY_COMPLETED, &completed_callback, NULL, 138 MHD_OPTION_NOTIFY_COMPLETED, &completed_callback, NULL,
139 MHD_OPTION_CONNECTION_LIMIT, (unsigned int) 1000,
137 MHD_OPTION_END); 140 MHD_OPTION_END);
138 if (d == NULL) 141 if (d == NULL)
139 return 1; 142 return 1;
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h
index f5397cc5..461c95cd 100644
--- a/src/include/microhttpd.h
+++ b/src/include/microhttpd.h
@@ -436,7 +436,13 @@ enum MHD_FLAG
436 /** 436 /**
437 * Use a single socket for IPv4 and IPv6. 437 * Use a single socket for IPv4 and IPv6.
438 */ 438 */
439 MHD_USE_DUAL_STACK = MHD_USE_IPv6 | 2048 439 MHD_USE_DUAL_STACK = MHD_USE_IPv6 | 2048,
440
441 /**
442 * Enable EPOLL turbo. Only useful with MHD_USE_EPOLL_LINUX_ONLY.
443 * Highly experimental, do not use in production yet.
444 */
445 MHD_USE_EPOLL_TURBO = 4096
440 446
441}; 447};
442 448
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c
index a16bf62d..de67f800 100644
--- a/src/microhttpd/connection.c
+++ b/src/microhttpd/connection.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of libmicrohttpd 2 This file is part of libmicrohttpd
3 (C) 2007, 2008, 2009, 2010, 2011, 2012 Daniel Pittman and Christian Grothoff 3 (C) 2007-2013 Daniel Pittman and Christian Grothoff
4 4
5 This library is free software; you can redistribute it and/or 5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public 6 modify it under the terms of the GNU Lesser General Public
@@ -266,8 +266,9 @@ MHD_connection_close (struct MHD_Connection *connection,
266 struct MHD_Daemon *daemon; 266 struct MHD_Daemon *daemon;
267 267
268 daemon = connection->daemon; 268 daemon = connection->daemon;
269 SHUTDOWN (connection->socket_fd, 269 if (0 == (connection->daemon->options & MHD_USE_EPOLL_TURBO))
270 (MHD_YES == connection->read_closed) ? SHUT_WR : SHUT_RDWR); 270 SHUTDOWN (connection->socket_fd,
271 (MHD_YES == connection->read_closed) ? SHUT_WR : SHUT_RDWR);
271 connection->state = MHD_CONNECTION_CLOSED; 272 connection->state = MHD_CONNECTION_CLOSED;
272 connection->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP; 273 connection->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP;
273 if ( (NULL != daemon->notify_completed) && 274 if ( (NULL != daemon->notify_completed) &&
@@ -1485,7 +1486,7 @@ do_read (struct MHD_Connection *connection)
1485 if (bytes_read < 0) 1486 if (bytes_read < 0)
1486 { 1487 {
1487 if ((EINTR == errno) || (EAGAIN == errno)) 1488 if ((EINTR == errno) || (EAGAIN == errno))
1488 return MHD_NO; 1489 return MHD_NO;
1489#if HAVE_MESSAGES 1490#if HAVE_MESSAGES
1490#if HTTPS_SUPPORT 1491#if HTTPS_SUPPORT
1491 if (0 != (connection->daemon->options & MHD_USE_SSL)) 1492 if (0 != (connection->daemon->options & MHD_USE_SSL))
@@ -2032,6 +2033,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
2032 int rend; 2033 int rend;
2033 char *line; 2034 char *line;
2034 2035
2036 connection->in_idle = MHD_YES;
2035 while (1) 2037 while (1)
2036 { 2038 {
2037#if DEBUG_STATES 2039#if DEBUG_STATES
@@ -2376,32 +2378,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
2376 } 2378 }
2377 continue; 2379 continue;
2378 case MHD_CONNECTION_CLOSED: 2380 case MHD_CONNECTION_CLOSED:
2379 if (connection->response != NULL) 2381 goto cleanup_connection;
2380 {
2381 MHD_destroy_response (connection->response);
2382 connection->response = NULL;
2383 }
2384 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
2385 (0 != pthread_mutex_lock (&daemon->cleanup_connection_mutex)) )
2386 MHD_PANIC ("Failed to acquire cleanup mutex\n");
2387 if (connection->connection_timeout == daemon->connection_timeout)
2388 XDLL_remove (daemon->normal_timeout_head,
2389 daemon->normal_timeout_tail,
2390 connection);
2391 else
2392 XDLL_remove (daemon->manual_timeout_head,
2393 daemon->manual_timeout_tail,
2394 connection);
2395 DLL_remove (daemon->connections_head,
2396 daemon->connections_tail,
2397 connection);
2398 DLL_insert (daemon->cleanup_head,
2399 daemon->cleanup_tail,
2400 connection);
2401 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
2402 (0 != pthread_mutex_unlock(&daemon->cleanup_connection_mutex)) )
2403 MHD_PANIC ("Failed to release cleanup mutex\n");
2404 return MHD_NO;
2405 default: 2382 default:
2406 EXTRA_CHECK (0); 2383 EXTRA_CHECK (0);
2407 break; 2384 break;
@@ -2413,35 +2390,109 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
2413 (timeout <= (MHD_monotonic_time() - connection->last_activity)) ) 2390 (timeout <= (MHD_monotonic_time() - connection->last_activity)) )
2414 { 2391 {
2415 MHD_connection_close (connection, MHD_REQUEST_TERMINATED_TIMEOUT_REACHED); 2392 MHD_connection_close (connection, MHD_REQUEST_TERMINATED_TIMEOUT_REACHED);
2393 connection->in_idle = MHD_NO;
2416 return MHD_YES; 2394 return MHD_YES;
2417 } 2395 }
2418 MHD_connection_update_event_loop_info (connection); 2396 MHD_connection_update_event_loop_info (connection);
2419 switch (connection->event_loop_info) 2397 switch (connection->event_loop_info)
2420 { 2398 {
2421 case MHD_EVENT_LOOP_INFO_READ: 2399 case MHD_EVENT_LOOP_INFO_READ:
2422 if (0 != (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) 2400 if ( (0 != (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) &&
2423 EDLL_insert (daemon->eready_head, 2401 (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL)) )
2424 daemon->eready_tail, 2402 {
2425 connection); 2403 EDLL_insert (daemon->eready_head,
2404 daemon->eready_tail,
2405 connection);
2406 connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
2407 }
2426 break; 2408 break;
2427 case MHD_EVENT_LOOP_INFO_WRITE: 2409 case MHD_EVENT_LOOP_INFO_WRITE:
2428 if (0 != (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY)) 2410 if ( (0 != (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY)) &&
2429 EDLL_insert (daemon->eready_head, 2411 (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL)) )
2430 daemon->eready_tail, 2412 {
2431 connection); 2413 EDLL_insert (daemon->eready_head,
2414 daemon->eready_tail,
2415 connection);
2416 connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
2417 }
2432 break; 2418 break;
2433 case MHD_EVENT_LOOP_INFO_BLOCK: 2419 case MHD_EVENT_LOOP_INFO_BLOCK:
2434 /* we should look at this connection again in the next iteration 2420 /* we should look at this connection again in the next iteration
2435 of the event loop, as we're waiting on the application */ 2421 of the event loop, as we're waiting on the application */
2436 EDLL_insert (daemon->eready_head, 2422 if (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
2437 daemon->eready_tail, 2423 {
2438 connection); 2424 EDLL_insert (daemon->eready_head,
2425 daemon->eready_tail,
2426 connection);
2427 connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
2428 }
2439 break; 2429 break;
2440 case MHD_EVENT_LOOP_INFO_CLEANUP: 2430 case MHD_EVENT_LOOP_INFO_CLEANUP:
2441 /* This connection is finished, nothing left to do */ 2431 /* This connection is finished, nothing left to do */
2442 break; 2432 break;
2443 } 2433 }
2434
2435#if EPOLL_SUPPORT
2436 if ( (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY)) &&
2437 (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) &&
2438 ( (0 == (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY)) ||
2439 ( (0 == (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) &&
2440 (MHD_EVENT_LOOP_INFO_READ == connection->event_loop_info) &&
2441 (MHD_NO == connection->read_closed) ) ) )
2442 {
2443 /* add to epoll set */
2444 struct epoll_event event;
2445
2446 event.events = EPOLLIN | EPOLLOUT | EPOLLET;
2447 event.data.ptr = connection;
2448 if (0 != epoll_ctl (daemon->epoll_fd,
2449 EPOLL_CTL_ADD,
2450 connection->socket_fd,
2451 &event))
2452 {
2453#if HAVE_MESSAGES
2454 if (0 != (daemon->options & MHD_USE_DEBUG))
2455 MHD_DLOG (daemon,
2456 "Call to epoll_ctl failed: %s\n",
2457 STRERROR (errno));
2458#endif
2459 connection->state = MHD_CONNECTION_CLOSED;
2460 goto cleanup_connection;
2461 }
2462 connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
2463 }
2464#endif
2465 connection->in_idle = MHD_NO;
2444 return MHD_YES; 2466 return MHD_YES;
2467
2468 cleanup_connection:
2469 if (NULL != connection->response)
2470 {
2471 MHD_destroy_response (connection->response);
2472 connection->response = NULL;
2473 }
2474 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
2475 (0 != pthread_mutex_lock (&daemon->cleanup_connection_mutex)) )
2476 MHD_PANIC ("Failed to acquire cleanup mutex\n");
2477 if (connection->connection_timeout == daemon->connection_timeout)
2478 XDLL_remove (daemon->normal_timeout_head,
2479 daemon->normal_timeout_tail,
2480 connection);
2481 else
2482 XDLL_remove (daemon->manual_timeout_head,
2483 daemon->manual_timeout_tail,
2484 connection);
2485 DLL_remove (daemon->connections_head,
2486 daemon->connections_tail,
2487 connection);
2488 DLL_insert (daemon->cleanup_head,
2489 daemon->cleanup_tail,
2490 connection);
2491 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
2492 (0 != pthread_mutex_unlock(&daemon->cleanup_connection_mutex)) )
2493 MHD_PANIC ("Failed to release cleanup mutex\n");
2494 connection->in_idle = MHD_NO;
2495 return MHD_NO;
2445} 2496}
2446 2497
2447 2498
@@ -2589,11 +2640,13 @@ MHD_queue_response (struct MHD_Connection *connection,
2589 /* response was queued "early", 2640 /* response was queued "early",
2590 refuse to read body / footers or further 2641 refuse to read body / footers or further
2591 requests! */ 2642 requests! */
2592 (void) SHUTDOWN (connection->socket_fd, SHUT_RD); 2643 if (0 == (connection->daemon->options & MHD_USE_EPOLL_TURBO))
2644 (void) SHUTDOWN (connection->socket_fd, SHUT_RD);
2593 connection->read_closed = MHD_YES; 2645 connection->read_closed = MHD_YES;
2594 connection->state = MHD_CONNECTION_FOOTERS_RECEIVED; 2646 connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2595 } 2647 }
2596 (void) MHD_connection_handle_idle (connection); 2648 if (MHD_NO == connection->in_idle)
2649 (void) MHD_connection_handle_idle (connection);
2597 return MHD_YES; 2650 return MHD_YES;
2598} 2651}
2599 2652
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index 1625078d..d111d9cd 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -809,7 +809,7 @@ recv_param_adapter (struct MHD_Connection *connection,
809 } 809 }
810 ret = RECV (connection->socket_fd, other, i, MSG_NOSIGNAL); 810 ret = RECV (connection->socket_fd, other, i, MSG_NOSIGNAL);
811#if EPOLL_SUPPORT 811#if EPOLL_SUPPORT
812 if (ret < i) 812 if (ret < (ssize_t) i)
813 { 813 {
814 /* partial read --- no longer read-ready */ 814 /* partial read --- no longer read-ready */
815 connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY; 815 connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
@@ -884,7 +884,7 @@ send_param_adapter (struct MHD_Connection *connection,
884#endif 884#endif
885 ret = SEND (connection->socket_fd, other, i, MSG_NOSIGNAL); 885 ret = SEND (connection->socket_fd, other, i, MSG_NOSIGNAL);
886#if EPOLL_SUPPORT 886#if EPOLL_SUPPORT
887 if (ret < i) 887 if (ret < (ssize_t) i)
888 { 888 {
889 /* partial write --- no longer write-ready */ 889 /* partial write --- no longer write-ready */
890 connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; 890 connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
@@ -1121,37 +1121,43 @@ MHD_add_connection (struct MHD_Daemon *daemon,
1121 MHD_set_http_callbacks_ (connection); 1121 MHD_set_http_callbacks_ (connection);
1122 connection->recv_cls = &recv_param_adapter; 1122 connection->recv_cls = &recv_param_adapter;
1123 connection->send_cls = &send_param_adapter; 1123 connection->send_cls = &send_param_adapter;
1124 /* non-blocking sockets are required on most systems and for GNUtls; 1124
1125 however, they somehow cause serious problems on CYGWIN (#1824) */ 1125 if (0 == (connection->daemon->options & MHD_USE_EPOLL_TURBO))
1126 {
1127 /* non-blocking sockets are required on most systems and for GNUtls;
1128 however, they somehow cause serious problems on CYGWIN (#1824);
1129 in turbo mode, we assume that non-blocking was already set
1130 by 'accept4' or whoever calls 'MHD_add_connection' */
1126#ifdef CYGWIN 1131#ifdef CYGWIN
1127 if (0 != (daemon->options & MHD_USE_SSL)) 1132 if (0 != (daemon->options & MHD_USE_SSL))
1128#endif 1133#endif
1129 { 1134 {
1130 /* make socket non-blocking */ 1135 /* make socket non-blocking */
1131#ifndef MINGW 1136#ifndef MINGW
1132 int flags = fcntl (connection->socket_fd, F_GETFL); 1137 int flags = fcntl (connection->socket_fd, F_GETFL);
1133 if ( (-1 == flags) || 1138 if ( (-1 == flags) ||
1134 (0 != fcntl (connection->socket_fd, F_SETFL, flags | O_NONBLOCK)) ) 1139 (0 != fcntl (connection->socket_fd, F_SETFL, flags | O_NONBLOCK)) )
1135 { 1140 {
1136#if HAVE_MESSAGES 1141#if HAVE_MESSAGES
1137 MHD_DLOG (daemon, 1142 MHD_DLOG (daemon,
1138 "Failed to make socket %d non-blocking: %s\n", 1143 "Failed to make socket %d non-blocking: %s\n",
1139 connection->socket_fd, 1144 connection->socket_fd,
1140 STRERROR (errno)); 1145 STRERROR (errno));
1141#endif 1146#endif
1142 } 1147 }
1143#else 1148#else
1144 unsigned long flags = 1; 1149 unsigned long flags = 1;
1145 if (0 != ioctlsocket (connection->socket_fd, FIONBIO, &flags)) 1150 if (0 != ioctlsocket (connection->socket_fd, FIONBIO, &flags))
1146 { 1151 {
1147#if HAVE_MESSAGES 1152#if HAVE_MESSAGES
1148 MHD_DLOG (daemon, 1153 MHD_DLOG (daemon,
1149 "Failed to make socket non-blocking: %s\n", 1154 "Failed to make socket non-blocking: %s\n",
1150 STRERROR (errno)); 1155 STRERROR (errno));
1151#endif 1156#endif
1152 } 1157 }
1153#endif 1158#endif
1154 } 1159 }
1160 }
1155 1161
1156#if HTTPS_SUPPORT 1162#if HTTPS_SUPPORT
1157 if (0 != (daemon->options & MHD_USE_SSL)) 1163 if (0 != (daemon->options & MHD_USE_SSL))
@@ -1228,25 +1234,35 @@ MHD_add_connection (struct MHD_Daemon *daemon,
1228#if EPOLL_SUPPORT 1234#if EPOLL_SUPPORT
1229 if (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY)) 1235 if (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY))
1230 { 1236 {
1231 struct epoll_event event; 1237 if (0 == (daemon->options & MHD_USE_EPOLL_TURBO))
1232
1233 event.events = EPOLLIN | EPOLLOUT | EPOLLET;
1234 event.data.ptr = connection;
1235 if (0 != epoll_ctl (daemon->epoll_fd,
1236 EPOLL_CTL_ADD,
1237 client_socket,
1238 &event))
1239 { 1238 {
1239 struct epoll_event event;
1240
1241 event.events = EPOLLIN | EPOLLOUT | EPOLLET;
1242 event.data.ptr = connection;
1243 if (0 != epoll_ctl (daemon->epoll_fd,
1244 EPOLL_CTL_ADD,
1245 client_socket,
1246 &event))
1247 {
1240#if HAVE_MESSAGES 1248#if HAVE_MESSAGES
1241 if (0 != (daemon->options & MHD_USE_DEBUG)) 1249 if (0 != (daemon->options & MHD_USE_DEBUG))
1242 MHD_DLOG (daemon, 1250 MHD_DLOG (daemon,
1243 "Call to epoll_ctl failed: %s\n", 1251 "Call to epoll_ctl failed: %s\n",
1244 STRERROR (errno)); 1252 STRERROR (errno));
1245#endif 1253#endif
1246 goto cleanup; 1254 goto cleanup;
1255 }
1256 connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
1257 }
1258 else
1259 {
1260 connection->epoll_state |= MHD_EPOLL_STATE_READ_READY | MHD_EPOLL_STATE_WRITE_READY
1261 | MHD_EPOLL_STATE_IN_EREADY_EDLL;
1262 EDLL_insert (daemon->eready_head,
1263 daemon->eready_tail,
1264 connection);
1247 } 1265 }
1248 daemon->listen_socket_in_epoll = MHD_YES;
1249
1250 } 1266 }
1251#endif 1267#endif
1252 daemon->max_connections--; 1268 daemon->max_connections--;
@@ -1300,13 +1316,19 @@ MHD_accept_connection (struct MHD_Daemon *daemon)
1300 socklen_t addrlen; 1316 socklen_t addrlen;
1301 int s; 1317 int s;
1302 int fd; 1318 int fd;
1319 int nonblock;
1303 1320
1304 addrlen = sizeof (addrstorage); 1321 addrlen = sizeof (addrstorage);
1305 memset (addr, 0, sizeof (addrstorage)); 1322 memset (addr, 0, sizeof (addrstorage));
1306 if (-1 == (fd = daemon->socket_fd)) 1323 if (-1 == (fd = daemon->socket_fd))
1307 return MHD_NO; 1324 return MHD_NO;
1325 nonblock = SOCK_NONBLOCK;
1326#ifdef CYGWIN
1327 if (0 == (daemon->options & MHD_USE_SSL))
1328 nonblock = 0;
1329#endif
1308#if HAVE_ACCEPT4 1330#if HAVE_ACCEPT4
1309 s = accept4 (fd, addr, &addrlen, SOCK_CLOEXEC); 1331 s = accept4 (fd, addr, &addrlen, SOCK_CLOEXEC | nonblock);
1310#else 1332#else
1311 s = ACCEPT (fd, addr, &addrlen); 1333 s = ACCEPT (fd, addr, &addrlen);
1312#endif 1334#endif
@@ -1329,9 +1351,19 @@ MHD_accept_connection (struct MHD_Daemon *daemon)
1329 } 1351 }
1330#if !HAVE_ACCEPT4 1352#if !HAVE_ACCEPT4
1331 { 1353 {
1332 /* make socket non-inheritable */ 1354 /* make socket non-inheritable and non-blocking */
1333#ifdef WINDOWS 1355#ifdef WINDOWS
1334 DWORD dwFlags; 1356 DWORD dwFlags;
1357 unsigned long flags = 1;
1358
1359 if (0 != ioctlsocket (s, FIONBIO, &flags))
1360 {
1361#if HAVE_MESSAGES
1362 MHD_DLOG (daemon,
1363 "Failed to make socket non-blocking: %s\n",
1364 STRERROR (errno));
1365#endif
1366 }
1335 if (!GetHandleInformation ((HANDLE) s, &dwFlags) || 1367 if (!GetHandleInformation ((HANDLE) s, &dwFlags) ||
1336 ((dwFlags != dwFlags & ~HANDLE_FLAG_INHERIT) && 1368 ((dwFlags != dwFlags & ~HANDLE_FLAG_INHERIT) &&
1337 !SetHandleInformation ((HANDLE) s, HANDLE_FLAG_INHERIT, 0))) 1369 !SetHandleInformation ((HANDLE) s, HANDLE_FLAG_INHERIT, 0)))
@@ -1342,14 +1374,19 @@ MHD_accept_connection (struct MHD_Daemon *daemon)
1342 "Failed to make socket non-inheritable: %s\n", 1374 "Failed to make socket non-inheritable: %s\n",
1343 STRERROR (errno)); 1375 STRERROR (errno));
1344#endif 1376#endif
1345 } 1377 }
1346#else 1378#else
1347 int flags; 1379 int flags;
1348 1380
1381 nonblock = O_NONBLOCK;
1382#ifdef CYGWIN
1383 if (0 == (daemon->options & MHD_USE_SSL))
1384 nonblock = 0;
1385#endif
1349 flags = fcntl (s, F_GETFD); 1386 flags = fcntl (s, F_GETFD);
1350 if ( ( (-1 == flags) || 1387 if ( ( (-1 == flags) ||
1351 ( (flags != (flags | FD_CLOEXEC)) && 1388 ( (flags != (flags | FD_CLOEXEC)) &&
1352 (0 != fcntl (s, F_SETFD, flags | FD_CLOEXEC)) ) ) ) 1389 (0 != fcntl (s, F_SETFD, flags | nonblock | FD_CLOEXEC)) ) ) )
1353 { 1390 {
1354#if HAVE_MESSAGES 1391#if HAVE_MESSAGES
1355 MHD_DLOG (daemon, 1392 MHD_DLOG (daemon,
@@ -1358,7 +1395,10 @@ MHD_accept_connection (struct MHD_Daemon *daemon)
1358#endif 1395#endif
1359 } 1396 }
1360#endif 1397#endif
1398 /* make socket non-blocking */
1399
1361 } 1400 }
1401
1362#endif 1402#endif
1363#if HAVE_MESSAGES 1403#if HAVE_MESSAGES
1364#if DEBUG_CONNECT 1404#if DEBUG_CONNECT
@@ -1406,10 +1446,13 @@ MHD_cleanup_connections (struct MHD_Daemon *daemon)
1406 if (pos->tls_session != NULL) 1446 if (pos->tls_session != NULL)
1407 gnutls_deinit (pos->tls_session); 1447 gnutls_deinit (pos->tls_session);
1408#endif 1448#endif
1409 MHD_ip_limit_del (daemon, (struct sockaddr*)pos->addr, pos->addr_len); 1449 MHD_ip_limit_del (daemon,
1450 (struct sockaddr *) pos->addr,
1451 pos->addr_len);
1410#if EPOLL_SUPPORT 1452#if EPOLL_SUPPORT
1411 if ( (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY)) && 1453 if ( (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY)) &&
1412 (-1 != daemon->epoll_fd) ) 1454 (-1 != daemon->epoll_fd) &&
1455 (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) )
1413 { 1456 {
1414 /* epoll documentation suggests that closing a FD 1457 /* epoll documentation suggests that closing a FD
1415 automatically removes it from the epoll set; however, 1458 automatically removes it from the epoll set; however,
@@ -1422,6 +1465,7 @@ MHD_cleanup_connections (struct MHD_Daemon *daemon)
1422 pos->socket_fd, 1465 pos->socket_fd,
1423 NULL)) 1466 NULL))
1424 MHD_PANIC ("Failed to remove FD from epoll set\n"); 1467 MHD_PANIC ("Failed to remove FD from epoll set\n");
1468 pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET;
1425 } 1469 }
1426#endif 1470#endif
1427 if (NULL != pos->response) 1471 if (NULL != pos->response)
@@ -1949,10 +1993,10 @@ MHD_poll (struct MHD_Daemon *daemon,
1949 1993
1950/** 1994/**
1951 * Do 'epoll'-based processing (this function is allowed to 1995 * Do 'epoll'-based processing (this function is allowed to
1952 * block). 1996 * block if 'may_block' is set to MHD_YES).
1953 * 1997 *
1954 * @param daemon daemon to run poll loop for 1998 * @param daemon daemon to run poll loop for
1955 * @param may_block YES if blocking, NO if non-blocking 1999 * @param may_block MHD_YES if blocking, MHD_NO if non-blocking
1956 * @return MHD_NO on serious errors, MHD_YES on success 2000 * @return MHD_NO on serious errors, MHD_YES on success
1957 */ 2001 */
1958static int 2002static int
@@ -1966,7 +2010,8 @@ MHD_epoll (struct MHD_Daemon *daemon,
1966 int timeout_ms; 2010 int timeout_ms;
1967 MHD_UNSIGNED_LONG_LONG timeout_ll; 2011 MHD_UNSIGNED_LONG_LONG timeout_ll;
1968 int num_events; 2012 int num_events;
1969 unsigned int i; 2013 unsigned int i;
2014 unsigned int series_length;
1970 2015
1971 if (-1 == daemon->epoll_fd) 2016 if (-1 == daemon->epoll_fd)
1972 return MHD_NO; /* we're down! */ 2017 return MHD_NO; /* we're down! */
@@ -2082,8 +2127,11 @@ MHD_epoll (struct MHD_Daemon *daemon,
2082 { 2127 {
2083 /* run 'accept' until it fails or we are not allowed to take 2128 /* run 'accept' until it fails or we are not allowed to take
2084 on more connections */ 2129 on more connections */
2130 series_length = 0;
2085 while ( (MHD_YES == MHD_accept_connection (daemon)) && 2131 while ( (MHD_YES == MHD_accept_connection (daemon)) &&
2086 (0 != daemon->max_connections) ) ; 2132 (0 != daemon->max_connections) &&
2133 (series_length < 128) )
2134 series_length++;
2087 } 2135 }
2088 } 2136 }
2089 } 2137 }
@@ -2094,7 +2142,7 @@ MHD_epoll (struct MHD_Daemon *daemon,
2094 EDLL_remove (daemon->eready_head, 2142 EDLL_remove (daemon->eready_head,
2095 daemon->eready_tail, 2143 daemon->eready_tail,
2096 pos); 2144 pos);
2097 pos->epoll_state -= MHD_EPOLL_STATE_IN_EREADY_EDLL; 2145 pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
2098 if (MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info) 2146 if (MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info)
2099 pos->read_handler (pos); 2147 pos->read_handler (pos);
2100 if (MHD_EVENT_LOOP_INFO_WRITE == pos->event_loop_info) 2148 if (MHD_EVENT_LOOP_INFO_WRITE == pos->event_loop_info)
diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h
index 61424ca5..5c5605a7 100644
--- a/src/microhttpd/internal.h
+++ b/src/microhttpd/internal.h
@@ -111,7 +111,12 @@ enum MHD_EpollState
111 /** 111 /**
112 * Is this connection currently in the 'eready' EDLL? 112 * Is this connection currently in the 'eready' EDLL?
113 */ 113 */
114 MHD_EPOLL_STATE_IN_EREADY_EDLL = 4 114 MHD_EPOLL_STATE_IN_EREADY_EDLL = 4,
115
116 /**
117 * Is this connection currently in the 'epoll' set?
118 */
119 MHD_EPOLL_STATE_IN_EPOLL_SET = 8
115 120
116 }; 121 };
117 122
@@ -719,6 +724,11 @@ struct MHD_Connection
719 */ 724 */
720 int thread_joined; 725 int thread_joined;
721 726
727 /**
728 * Are we currently inside the "idle" handler (to avoid recursively invoking it).
729 */
730 int in_idle;
731
722#if EPOLL_SUPPORT 732#if EPOLL_SUPPORT
723 /** 733 /**
724 * What is the state of this socket in relation to epoll? 734 * What is the state of this socket in relation to epoll?