commit 47fdebac4b2a16ef84ef96e11ebdc2b1d1310fd8
parent eba022ce02aef76fd7d4babed1ce248d50427112
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
Date: Wed, 8 Feb 2017 22:33:29 +0300
Rewrote epoll handling: handle all connections instead of drying last active
Diffstat:
3 files changed, 37 insertions(+), 52 deletions(-)
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c
@@ -3227,52 +3227,9 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
MHD_connection_update_event_loop_info (connection);
#ifdef EPOLL_SUPPORT
if (0 != (daemon->options & MHD_USE_EPOLL))
- {
- switch (connection->event_loop_info)
- {
- case MHD_EVENT_LOOP_INFO_READ:
- if ( (0 != (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) &&
- (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) &&
- (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)) &&
- (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) &&
- (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 */
- if ( (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) &&
- (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED))) )
- {
- 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;
- }
- }
- return MHD_connection_epoll_update_ (connection);
-#else
+ return MHD_connection_epoll_update_ (connection);
+#endif /* EPOLL_SUPPORT */
return MHD_YES;
-#endif
}
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
@@ -2900,6 +2900,15 @@ MHD_get_timeout (struct MHD_Daemon *daemon,
return MHD_YES;
}
#endif /* HTTPS_SUPPORT */
+#ifdef EPOLL_SUPPORT
+ if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
+ (NULL != daemon->eready_head) )
+ {
+ /* Some connection(s) already have some data pending. */
+ *timeout = 0;
+ return MHD_YES;
+ }
+#endif /* EPOLL_SUPPORT */
have_timeout = MHD_NO;
earliest_deadline = 0; /* avoid compiler warnings */
@@ -3685,6 +3694,7 @@ MHD_epoll (struct MHD_Daemon *daemon,
#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
struct MHD_Connection *pos;
struct MHD_Connection *next;
+ struct MHD_Connection *prev;
struct epoll_event events[MAX_EVENTS];
struct epoll_event event;
int timeout_ms;
@@ -3887,16 +3897,31 @@ MHD_epoll (struct MHD_Daemon *daemon,
(void) resume_suspended_connections (daemon);
/* process events for connections */
- while (NULL != (pos = daemon->eready_tail))
+ prev = daemon->eready_tail;
+ while (NULL != (pos = prev))
{
- EDLL_remove (daemon->eready_head,
- daemon->eready_tail,
- pos);
- pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
+ prev = pos->prevE;
+ /* FIXME: use (0 != pos->epoll_state & MHD_EPOLL_STATE_READ_READY) ? MHD_YES : MHD_NO
+ * and (0 != pos->epoll_state & MHD_EPOLL_STATE_WRITE_READY) ? MHD_YES : MHD_NO */
call_handlers (pos,
- MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info,
- MHD_EVENT_LOOP_INFO_WRITE == pos->event_loop_info,
+ (MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info) ? MHD_YES : MHD_NO,
+ (MHD_EVENT_LOOP_INFO_WRITE == pos->event_loop_info) ? MHD_YES : MHD_NO,
MHD_NO);
+ if (MHD_EPOLL_STATE_IN_EREADY_EDLL ==
+ (pos->epoll_state & (MHD_EPOLL_STATE_SUSPENDED | MHD_EPOLL_STATE_IN_EREADY_EDLL)))
+ {
+ if ( (MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info &&
+ 0 == (pos->epoll_state & MHD_EPOLL_STATE_READ_READY) ) ||
+ (MHD_EVENT_LOOP_INFO_WRITE == pos->event_loop_info &&
+ 0 == (pos->epoll_state & MHD_EPOLL_STATE_WRITE_READY) ) ||
+ MHD_EVENT_LOOP_INFO_CLEANUP == pos->event_loop_info)
+ {
+ EDLL_remove (daemon->eready_head,
+ daemon->eready_tail,
+ pos);
+ pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
+ }
+ }
}
/* Finally, handle timed-out connections; we need to do this here
diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h
@@ -884,16 +884,19 @@ struct MHD_Connection
/**
* Handler used for processing read connection operations
+ * @sa #MHD_connection_handle_read, #MHD_tls_connection_handle_read
*/
int (*read_handler) (struct MHD_Connection *connection);
/**
* Handler used for processing write connection operations
+ * @sa #MHD_connection_handle_write, #MHD_tls_connection_handle_write
*/
int (*write_handler) (struct MHD_Connection *connection);
/**
* Handler used for processing idle connection operations
+ * @sa #MHD_connection_handle_idle, #MHD_tls_connection_handle_idle
*/
int (*idle_handler) (struct MHD_Connection *connection);