commit d95ee55386fd05a14e9439f0b798ddd2b185b540
parent 53673f6b2174dd752abde08c0181093e9aca7b71
Author: Christian Grothoff <christian@grothoff.org>
Date: Sun, 13 Nov 2016 19:19:20 +0100
fixes to fix Doppelbauer testcase
Diffstat:
2 files changed, 37 insertions(+), 14 deletions(-)
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c
@@ -2379,6 +2379,8 @@ update_last_activity (struct MHD_Connection *connection)
connection->last_activity = MHD_monotonic_sec_counter();
if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
return; /* each connection has personal timeout */
+ if (connection->suspended)
+ return; /* not timeouts for suspended connections */
if (connection->connection_timeout != daemon->connection_timeout)
return; /* custom timeout, no need to move it in "normal" DLL */
@@ -2541,7 +2543,6 @@ MHD_connection_handle_write (struct MHD_Connection *connection)
MHD_CONNECTION_HEADERS_SENT);
break;
case MHD_CONNECTION_HEADERS_SENT:
- EXTRA_CHECK (0);
break;
case MHD_CONNECTION_NORMAL_BODY_READY:
response = connection->response;
@@ -2663,9 +2664,11 @@ cleanup_connection (struct MHD_Connection *connection)
{
struct MHD_Daemon *daemon = connection->daemon;
+ /* FIXME: when can this flag ever be needed? Sounds like we should
+ avoid this happening in the first place. Also, could there then
+ not be a race in this case? */
if (connection->in_cleanup)
return; /* Prevent double cleanup. */
-
connection->in_cleanup = true;
if (NULL != connection->response)
{
@@ -2685,17 +2688,21 @@ cleanup_connection (struct MHD_Connection *connection)
connection);
}
if (connection->suspended)
- DLL_remove (daemon->suspended_connections_head,
- daemon->suspended_connections_tail,
- connection);
+ {
+ DLL_remove (daemon->suspended_connections_head,
+ daemon->suspended_connections_tail,
+ connection);
+ connection->suspended = false;
+ }
else
- DLL_remove (daemon->connections_head,
- daemon->connections_tail,
- connection);
+ {
+ DLL_remove (daemon->connections_head,
+ daemon->connections_tail,
+ connection);
+ }
DLL_insert (daemon->cleanup_head,
daemon->cleanup_tail,
connection);
- connection->suspended = false;
connection->resuming = false;
connection->in_idle = false;
MHD_mutex_unlock_chk_(&daemon->cleanup_connection_mutex);
@@ -2739,6 +2746,11 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
connection->in_idle = true;
while (1)
{
+ if (connection->suspended)
+ {
+ connection->in_idle = false;
+ return MHD_YES;
+ }
#if DEBUG_STATES
MHD_DLOG (daemon,
_("In function %s handling connection at state: %s\n"),
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
@@ -2343,12 +2343,18 @@ internal_add_connection (struct MHD_Daemon *daemon,
void
MHD_suspend_connection (struct MHD_Connection *connection)
{
- struct MHD_Daemon *daemon;
+ struct MHD_Daemon *daemon = connection->daemon;
- daemon = connection->daemon;
if (MHD_ALLOW_SUSPEND_RESUME != (daemon->options & MHD_ALLOW_SUSPEND_RESUME))
MHD_PANIC (_("Cannot suspend connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n"));
MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
+ if (connection->resuming)
+ {
+ /* suspending again while we didn't even complete resuming yet */
+ connection->resuming = false;
+ MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
+ return;
+ }
if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
{
if (connection->connection_timeout == daemon->connection_timeout)
@@ -2363,9 +2369,11 @@ MHD_suspend_connection (struct MHD_Connection *connection)
DLL_remove (daemon->connections_head,
daemon->connections_tail,
connection);
+ EXTRA_CHECK (! connection->suspended);
DLL_insert (daemon->suspended_connections_head,
daemon->suspended_connections_tail,
connection);
+ connection->suspended = true;
#ifdef EPOLL_SUPPORT
if (0 != (daemon->options & MHD_USE_EPOLL))
{
@@ -2388,7 +2396,6 @@ MHD_suspend_connection (struct MHD_Connection *connection)
connection->epoll_state |= MHD_EPOLL_STATE_SUSPENDED;
}
#endif
- connection->suspended = true;
MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
}
@@ -2447,8 +2454,11 @@ resume_suspended_connections (struct MHD_Daemon *daemon)
next = daemon->suspended_connections_head;
/* Clear the flag *only* if connections will be resumed otherwise
it may accidentally clear flag that was set at the same time in
- other thread (just after 'if (MHD_NO != daemon->resuming)' in
+ another thread (just after 'if (MHD_NO != daemon->resuming)' in
this thread).
+
+ FIXME: is this not prevented by the lock!?
+
Clear flag *before* resuming connections otherwise new connection can
be set to "resuming" in other thread, but missed resuming in this
function at this time so clearing flag at end will clear it without
@@ -2472,9 +2482,11 @@ resume_suspended_connections (struct MHD_Daemon *daemon)
)
continue;
ret = MHD_YES;
+ EXTRA_CHECK (pos->suspended);
DLL_remove (daemon->suspended_connections_head,
daemon->suspended_connections_tail,
pos);
+ pos->suspended = false;
if (NULL == urh)
{
DLL_insert (daemon->connections_head,
@@ -2518,7 +2530,6 @@ resume_suspended_connections (struct MHD_Daemon *daemon)
}
#endif /* UPGRADE_SUPPORT */
- pos->suspended = false;
pos->resuming = false;
}
MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);