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:
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;