libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

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:
Msrc/microhttpd/connection.c | 47++---------------------------------------------
Msrc/microhttpd/daemon.c | 39++++++++++++++++++++++++++++++++-------
Msrc/microhttpd/internal.h | 3+++
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);