diff options
| author | Stefan Boberg <[email protected]> | 2023-09-15 09:06:24 +0200 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-09-15 09:06:24 +0200 |
| commit | a70ad011ed4b32c150421a735ed308df2b79bb24 (patch) | |
| tree | 096f84c1a7aa338c7eaa3f4a1754b3c9dbeafe9e /src/zenhttp/httpsys.cpp | |
| parent | 0.2.21 (diff) | |
| download | zen-a70ad011ed4b32c150421a735ed308df2b79bb24.tar.xz zen-a70ad011ed4b32c150421a735ed308df2b79bb24.zip | |
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
Diffstat (limited to 'src/zenhttp/httpsys.cpp')
| -rw-r--r-- | src/zenhttp/httpsys.cpp | 15 |
1 files changed, 14 insertions, 1 deletions
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; |