libmicrohttpd

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

commit a559950eb866af16cffb6cfa9ac7d2fa12274f73
parent edb0845e3542c9b606e45a4606b6bff57e1f98aa
Author: Christian Grothoff <christian@grothoff.org>
Date:   Sat, 20 Jul 2013 10:36:26 +0000

-fix combining HTTPS and EPOLL

Diffstat:
MChangeLog | 3+++
Msrc/examples/benchmark_https.c | 2+-
Msrc/microhttpd/connection.c | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
Msrc/microhttpd/connection.h | 14++++++++++++++
Msrc/microhttpd/connection_https.c | 5+++--
Msrc/microhttpd/daemon.c | 4++++
6 files changed, 90 insertions(+), 35 deletions(-)

diff --git a/ChangeLog b/ChangeLog @@ -1,3 +1,6 @@ +Sat Jul 20 12:35:40 CEST 2013 + Fixing combination of MHD_USE_SSL and MHD_USE_EPOLL_LINUX_ONLY. -CG + Fri Jul 19 09:57:27 CEST 2013 Fix issue where connections were not cleaned up when 'MHD_run_from_select' was used. Adding experimental diff --git a/src/examples/benchmark_https.c b/src/examples/benchmark_https.c @@ -178,7 +178,7 @@ main (int argc, char *const *argv) "close"); d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_SUPPRESS_DATE_NO_CLOCK | MHD_USE_SSL #if EPOLL_SUPPORT - | MHD_USE_EPOLL_LINUX_ONLY | MHD_USE_EPOLL_TURBO + | MHD_USE_EPOLL_LINUX_ONLY | MHD_USE_EPOLL_TURBO #endif , atoi (argv[1]), diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c @@ -2017,6 +2017,46 @@ MHD_connection_handle_write (struct MHD_Connection *connection) /** + * Clean up the state of the given connection and move it into the + * clean up queue for final disposal. + * + * @param connection handle for the connection to clean up + */ +static void +cleanup_connection (struct MHD_Connection *connection) +{ + struct MHD_Daemon *daemon = connection->daemon; + + 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; +} + + +/** * This function was created to handle per-connection processing that * has to happen even if the socket cannot be read or written to. * @@ -2378,7 +2418,8 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) } continue; case MHD_CONNECTION_CLOSED: - goto cleanup_connection; + cleanup_connection (connection); + return MHD_NO; default: EXTRA_CHECK (0); break; @@ -2431,8 +2472,28 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) /* This connection is finished, nothing left to do */ break; } +#if EPOLL_SUPPORT + return MHD_connection_epoll_update_ (connection); +#else + return MHD_YES; +#endif +} + #if EPOLL_SUPPORT +/** + * Perform epoll processing, possibly moving the connection back into + * the epoll set if needed. + * + * @param connection connection to process + * @return MHD_YES if we should continue to process the + * connection (not dead yet), MHD_NO if it died + */ +int +MHD_connection_epoll_update_ (struct MHD_Connection *connection) +{ + struct MHD_Daemon *daemon = connection->daemon; + 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)) || @@ -2457,43 +2518,15 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) STRERROR (errno)); #endif connection->state = MHD_CONNECTION_CLOSED; - goto cleanup_connection; + cleanup_connection (connection); + return MHD_NO; } 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; } +#endif /** diff --git a/src/microhttpd/connection.h b/src/microhttpd/connection.h @@ -93,4 +93,18 @@ MHD_connection_close (struct MHD_Connection *connection, enum MHD_RequestTerminationCode termination_code); +#if EPOLL_SUPPORT +/** + * Perform epoll processing, possibly moving the connection back into + * the epoll set if needed. + * + * @param connection connection to process + * @return MHD_YES if we should continue to process the + * connection (not dead yet), MHD_NO if it died + */ +int +MHD_connection_epoll_update_ (struct MHD_Connection *connection); +#endif + + #endif diff --git a/src/microhttpd/connection_https.c b/src/microhttpd/connection_https.c @@ -131,6 +131,7 @@ MHD_tls_connection_handle_write (struct MHD_Connection *connection) static int MHD_tls_connection_handle_idle (struct MHD_Connection *connection) { + struct MHD_Daemon *daemon = connection->daemon; unsigned int timeout; #if DEBUG_STATES @@ -145,7 +146,7 @@ MHD_tls_connection_handle_idle (struct MHD_Connection *connection) { /* on newly created connections we might reach here before any reply has been received */ case MHD_TLS_CONNECTION_INIT: - return MHD_YES; + break; /* close connection if necessary */ case MHD_CONNECTION_CLOSED: gnutls_bye (connection->tls_session, GNUTLS_SHUT_RDWR); @@ -156,7 +157,7 @@ MHD_tls_connection_handle_idle (struct MHD_Connection *connection) return MHD_YES; return MHD_connection_handle_idle (connection); } - return MHD_YES; + return MHD_connection_epoll_update_ (connection); } diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c @@ -400,7 +400,9 @@ recv_tls_adapter (struct MHD_Connection *connection, void *other, size_t i) if ( (GNUTLS_E_AGAIN == res) || (GNUTLS_E_INTERRUPTED == res) ) { + fprintf (stderr, "RAGAIN!\n"); errno = EINTR; + connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY; return -1; } if (res < 0) @@ -438,7 +440,9 @@ send_tls_adapter (struct MHD_Connection *connection, if ( (GNUTLS_E_AGAIN == res) || (GNUTLS_E_INTERRUPTED == res) ) { + fprintf (stderr, "WAGAIN!\n"); errno = EINTR; + connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; return -1; } return res;