From a70ad011ed4b32c150421a735ed308df2b79bb24 Mon Sep 17 00:00:00 2001 From: Stefan Boberg Date: Fri, 15 Sep 2023 09:06:24 +0200 Subject: bugfix: http.sys async response handling race (#406) under heavy load, an async response could end up deleting the HTTP transaction object before the issuing call had completed --- src/zenhttp/httpsys.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'src/zenhttp/httpsys.cpp') diff --git a/src/zenhttp/httpsys.cpp b/src/zenhttp/httpsys.cpp index 2f8e0a898..342fdd047 100644 --- a/src/zenhttp/httpsys.cpp +++ b/src/zenhttp/httpsys.cpp @@ -242,6 +242,14 @@ public: HttpSysServerRequest& ServerRequest() { return m_HandlerRequest.value(); } + struct CompletionMutexScope + { + CompletionMutexScope(HttpSysTransaction& Tx) : Lock(Tx.m_CompletionMutex) {} + ~CompletionMutexScope() = default; + + RwLock::ExclusiveLockScope Lock; + }; + private: OVERLAPPED m_HttpOverlapped{}; HttpSysServer& m_HttpServer; @@ -680,7 +688,12 @@ HttpAsyncWorkRequest::AsyncWorkItem::Execute() try { - HttpSysServerRequest& ThisRequest = Tx.ServerRequest(); + // We need to hold this lock while we're issuing new requests in order to + // prevent race conditions between the thread we are running on and any + // IOCP service threads. Otherwise the IOCP completion handler can end + // up deleting the transaction object before we are done with it! + HttpSysTransaction::CompletionMutexScope _(Tx); + HttpSysServerRequest& ThisRequest = Tx.ServerRequest(); ThisRequest.m_NextCompletionHandler = nullptr; -- cgit v1.2.3