diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/OnlineServices_Init.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/OnlineServices_Init.h index e141cecb93c..406222fce3d 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/OnlineServices_Init.h +++ b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/OnlineServices_Init.h @@ -398,6 +398,15 @@ class NGMP_OnlineServicesManager ~NGMP_OnlineServicesManager() { + // IMPORTANT: Delete HTTPManager BEFORE deleting interface objects + // HTTPManager::Shutdown() will invoke completion callbacks, which may reference interface objects + // We must ensure interfaces are still valid when callbacks execute + if (m_pHTTPManager != nullptr) + { + delete m_pHTTPManager; + m_pHTTPManager = nullptr; + } + if (m_pAuthInterface != nullptr) { delete m_pAuthInterface; @@ -422,12 +431,6 @@ class NGMP_OnlineServicesManager m_pRoomInterface = nullptr; } - if (m_pHTTPManager != nullptr) - { - delete m_pHTTPManager; - m_pHTTPManager = nullptr; - } - // Reset shared_ptr, which will delete WebSocket only when all references are released m_pWebSocket.reset(); } diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/HTTP/HTTPRequest.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/HTTP/HTTPRequest.cpp index ac07945109e..91a2efb731c 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/HTTP/HTTPRequest.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/HTTP/HTTPRequest.cpp @@ -104,7 +104,13 @@ void HTTPRequest::InvokeCallbackIfComplete() { strResponse.clear(); } + + // Invoke the callback m_completionCallback(true, m_responseCode, strResponse, this); + + // Clear the callback immediately after invocation to prevent use-after-free + // during std::function cleanup, especially during shutdown scenarios + m_completionCallback = nullptr; } } }