libmicrohttpd

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

commit 1778d7b8fe82dd0d9def0898968aa342957a468f
parent 0bfdd8d71ab43b0aa0b880503a651d58e112ef98
Author: Christian Grothoff <christian@grothoff.org>
Date:   Fri,  7 Aug 2026 21:18:39 +0200

fix assertion failure on resume

Diffstat:
Msrc/microhttpd/daemon.c | 25+++++++++++++++++++++++++
Msrc/microhttpd/internal.h | 15+++++++++++++++
2 files changed, 40 insertions(+), 0 deletions(-)

diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c @@ -1351,6 +1351,21 @@ call_handlers (struct MHD_Connection *con, if (con->tls_read_ready) read_ready = true; #endif /* HTTPS_SUPPORT */ + if (con->resumed) + { + /* The connection was resumed since its states were last updated, + so 'con->event_loop_info' still describes the state the + connection was in before it was suspended -- see the field's + description. Dispatching on it would, for instance, call + MHD_connection_handle_write() on a connection whose content + reader has just reported that it has no data yet, which is not a + state the write handler has an action for. */ + con->resumed = false; + ret = MHD_connection_handle_idle (con); + if (MHD_NO == ret) + return ret; /* Connection died and was cleaned up. */ + states_info_processed = true; + } if ( (0 != (MHD_EVENT_LOOP_INFO_READ & con->event_loop_info)) && (read_ready || (force_close && con->sk_nonblck)) ) { @@ -3577,6 +3592,16 @@ resume_suspended_connections (struct MHD_Daemon *daemon) pos); if (! used_thr_p_c) { + /* The states of a suspended connection are not updated, so they + are stale now that it is running again. Updating them here + would mean running the state machine under the cleanup mutex, + which is what 0ecf4f26e4c1a4c03d66e1d04bf4cae62bd236a0 backed + out of; flag the connection instead and let call_handlers() + update it before it acts on @e event_loop_info. Thread-per- + connection does the same for itself, in + thread_main_handle_connection(). */ + pos->resumed = true; + /* Reset timeout timer on resume. */ if (0 != pos->connection_timeout_ms) pos->last_activity = MHD_monotonic_msec_counter (); diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h @@ -1627,6 +1627,21 @@ struct MHD_Connection volatile bool resuming; /** + * Has the connection been resumed without its states having been + * updated since? + * + * #MHD_connection_update_event_loop_info() deliberately does not + * touch a suspended connection, so whatever the application did + * while the connection was suspended -- queueing a response, or the + * content reader reporting that it has no data yet and moving the + * connection to #MHD_CONNECTION_NORMAL_BODY_UNREADY -- leaves + * @e event_loop_info describing the state from before the + * suspension. The event loop must not act on that stale value; see + * the use in call_handlers(). + */ + bool resumed; + + /** * Special member to be returned by #MHD_get_connection_info() */ union MHD_ConnectionInfo connection_info_dummy;