From bf5dd318a7d8f4bed5cdb933bb560317303e3185 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Thu, 4 Apr 2024 18:49:00 +0200 Subject: [PATCH] Core: fix several initialization bugs - Don't free console if the process is being closed from the console, this will cause the process to freeze within the FreeConsole() call - Properly check for CPU features in order, and moved all checks to a single function utilizing the CPUInformation struct. - Made SDK_Init() and SDK_Shutdown() more resilient against mistakes with new checks and error messages (added since they are exported now). --- r5dev/core/dllmain.cpp | 46 +++++++++++++++++++++++++++++++--- r5dev/core/init.cpp | 27 -------------------- r5dev/core/init.h | 2 +- r5dev/mathlib/mathlib_base.cpp | 5 ---- r5dev/tier0/cpu.cpp | 28 ++++++++++++++++++--- r5dev/tier0/cpu.h | 20 +++++++++------ r5dev/windows/system.cpp | 17 ++++++++----- 7 files changed, 91 insertions(+), 54 deletions(-) diff --git a/r5dev/core/dllmain.cpp b/r5dev/core/dllmain.cpp index e91664fb..5415390a 100644 --- a/r5dev/core/dllmain.cpp +++ b/r5dev/core/dllmain.cpp @@ -3,6 +3,7 @@ #include "core/init.h" #include "core/logdef.h" #include "core/logger.h" +#include "tier0/cpu.h" #include "tier0/basetypes.h" #include "tier0/crashhandler.h" #include "tier0/commandline.h" @@ -24,6 +25,11 @@ #endif bool g_bSdkInitialized = false; + +bool g_bSdkInitCallInitiated = false; +bool g_bSdkShutdownCallInitiated = false; + +bool g_bSdkShutdownInitiatedFromConsoleHandler = false; HMODULE s_hModuleHandle = NULL; //############################################################################# @@ -77,7 +83,21 @@ void Tier0_Init() void SDK_Init() { - CheckCPU(); // Check CPU as early as possible; error out if CPU isn't supported. + assert(!g_bSdkInitialized); + + CheckSystemCPU(); // Check CPU as early as possible; error out if CPU isn't supported. + + if (g_bSdkInitCallInitiated) + { + spdlog::error("Recursive initialization!\n"); + return; + } + + // Set after checking cpu and initializing MathLib since we check CPU + // features there. Else we crash on the recursive initialization error as + // SpdLog uses SSE features. + g_bSdkInitCallInitiated = true; + MathLib_Init(); // Initialize Mathlib. PEB64* pEnv = CModule::GetProcessEnvironmentBlock(); @@ -129,13 +149,25 @@ void SDK_Shutdown() { assert(g_bSdkInitialized); - if (!g_bSdkInitialized) + // Also check CPU in shutdown, since this function is exported, if they + // call this with an unsupported CPU we should let them know rather than + // crashing the process. + CheckSystemCPU(); + + if (g_bSdkShutdownCallInitiated) { spdlog::error("Recursive shutdown!\n"); return; } - g_bSdkInitialized = false; + g_bSdkShutdownCallInitiated = true; + + if (!g_bSdkInitialized) + { + spdlog::error("Not initialized!\n"); + return; + } + Msg(eDLL_T::NONE, "GameSDK shutdown initiated\n"); curl_global_cleanup(); @@ -151,7 +183,13 @@ void SDK_Shutdown() Winsock_Shutdown(); SpdLog_Shutdown(); - Console_Shutdown(); + + // If the shutdown was initiated from the console window itself, don't + // shutdown the console as it would otherwise deadlock in FreeConsole! + if (!g_bSdkShutdownInitiatedFromConsoleHandler) + Console_Shutdown(); + + g_bSdkInitialized = false; } //############################################################################# diff --git a/r5dev/core/init.cpp b/r5dev/core/init.cpp index 13f7b8b9..3677676d 100644 --- a/r5dev/core/init.cpp +++ b/r5dev/core/init.cpp @@ -418,33 +418,6 @@ void QuerySystemInfo() } } -void CheckCPU() // Respawn's engine and our SDK utilize POPCNT, SSE3 and SSSE3 (Supplemental SSE 3 Instructions). -{ - CpuIdResult_t cpuResult; - __cpuid(reinterpret_cast(&cpuResult), 1); - - char szBuf[1024]; - - if ((cpuResult.ecx & (1 << 0)) == 0) - { - V_snprintf(szBuf, sizeof(szBuf), "CPU does not have %s!\n", "SSE 3"); - MessageBoxA(NULL, szBuf, "Unsupported CPU", MB_ICONERROR | MB_OK); - ExitProcess(0xFFFFFFFF); - } - if ((cpuResult.ecx & (1 << 9)) == 0) - { - V_snprintf(szBuf, sizeof(szBuf), "CPU does not have %s!\n", "SSSE 3 (Supplemental SSE 3 Instructions)"); - MessageBoxA(NULL, szBuf, "Unsupported CPU", MB_ICONERROR | MB_OK); - ExitProcess(0xFFFFFFFF); - } - if ((cpuResult.ecx & (1 << 23)) == 0) - { - V_snprintf(szBuf, sizeof(szBuf), "CPU does not have %s!\n", "POPCNT"); - MessageBoxA(NULL, szBuf, "Unsupported CPU", MB_ICONERROR | MB_OK); - ExitProcess(0xFFFFFFFF); - } -} - #if defined (DEDICATED) #define SIGDB_FILE "cfg/server/startup.bin" #elif defined (CLIENT_DLL) diff --git a/r5dev/core/init.h b/r5dev/core/init.h index 1cc51c5f..7b35872c 100644 --- a/r5dev/core/init.h +++ b/r5dev/core/init.h @@ -11,10 +11,10 @@ void Winsock_Shutdown(); void DirtySDK_Startup(); void DirtySDK_Shutdown(); void QuerySystemInfo(); -void CheckCPU(); void DetourInit(); void DetourAddress(); void DetourRegister(); extern bool g_bSdkInitialized; +extern bool g_bSdkShutdownInitiatedFromConsoleHandler; diff --git a/r5dev/mathlib/mathlib_base.cpp b/r5dev/mathlib/mathlib_base.cpp index 65602e24..1a87be64 100644 --- a/r5dev/mathlib/mathlib_base.cpp +++ b/r5dev/mathlib/mathlib_base.cpp @@ -4059,11 +4059,6 @@ void MathLib_Init(float gamma, float texGamma, float brightness, int overbright) // FIXME: Hook SSE into VectorAligned + Vector4DAligned -#if !defined( _GAMECONSOLE ) - CheckCPUforSSE2(); -#endif //!360 - - s_bMathlibInitialized = true; InitSinCosTable(); diff --git a/r5dev/tier0/cpu.cpp b/r5dev/tier0/cpu.cpp index b450daeb..7393b4bd 100644 --- a/r5dev/tier0/cpu.cpp +++ b/r5dev/tier0/cpu.cpp @@ -470,7 +470,9 @@ const CPUInformation& GetCPUInformation(void) pi.m_bSSE41 = (cpuid1.ecx >> 19) & 1; pi.m_bSSE42 = (cpuid1.ecx >> 20) & 1; pi.m_b3DNow = Check3DNowTechnology(); + pi.m_bPOPCNT= (cpuid1.ecx >> 23) & 1; pi.m_bAVX = (cpuid1.ecx >> 28) & 1; + pi.m_bHRVSR = (cpuid1.ecx >> 31) & 1; pi.m_szProcessorID = const_cast(GetProcessorVendorId()); pi.m_szProcessorBrand = const_cast(GetProcessorBrand()); pi.m_bHT = (pi.m_nPhysicalProcessors < pi.m_nLogicalProcessors); //HTSupported(); @@ -573,16 +575,36 @@ const CPUInformation& GetCPUInformation(void) return pi; } -void CheckCPUforSSE2() +void CheckSystemCPU() { const CPUInformation& pi = GetCPUInformation(); if (!(pi.m_bSSE && pi.m_bSSE2)) { - Assert(0); if (MessageBoxA(NULL, "SSE and SSE2 are required.", "Unsupported CPU", MB_ICONERROR | MB_OK)) { - TerminateProcess(GetCurrentProcess(), EXIT_FAILURE); + TerminateProcess(GetCurrentProcess(), 0xFFFFFFFF); + } + } + if (!pi.m_bSSE3) + { + if (MessageBoxA(NULL, "SSE3 is required.", "Unsupported CPU", MB_ICONERROR | MB_OK)) + { + TerminateProcess(GetCurrentProcess(), 0xFFFFFFFF); + } + } + if (!pi.m_bSSSE3) + { + if (MessageBoxA(NULL, "SSSE3 (Supplemental SSE3 Instructions) is required.", "Unsupported CPU", MB_ICONERROR | MB_OK)) + { + TerminateProcess(GetCurrentProcess(), 0xFFFFFFFF); + } + } + if (!pi.m_bPOPCNT) + { + if (MessageBoxA(NULL, "POPCNT is required.", "Unsupported CPU", MB_ICONERROR | MB_OK)) + { + TerminateProcess(GetCurrentProcess(), 0xFFFFFFFF); } } } diff --git a/r5dev/tier0/cpu.h b/r5dev/tier0/cpu.h index 52cf16bc..4425c486 100644 --- a/r5dev/tier0/cpu.h +++ b/r5dev/tier0/cpu.h @@ -62,7 +62,9 @@ struct CPUInformation m_bSSE4a : 1, m_bSSE41 : 1, m_bSSE42 : 1, - m_bAVX : 1; // Is AVX supported? + m_bPOPCNT: 1, // Pop count + m_bAVX : 1, // Advanced Vector Extensions + m_bHRVSR : 1; // Hypervisor uint32 m_nModel; uint32 m_nFeatures[3]; @@ -94,12 +96,14 @@ struct CPUInformation m_szProcessorID = nullptr; m_szProcessorBrand = nullptr; - m_bSSE3 = false; - m_bSSSE3 = false; - m_bSSE4a = false; - m_bSSE41 = false; - m_bSSE42 = false; - m_bAVX = false; + m_bSSE3 = false; + m_bSSSE3 = false; + m_bSSE4a = false; + m_bSSE41 = false; + m_bSSE42 = false; + m_bPOPCNT = false; + m_bAVX = false; + m_bHRVSR = false; m_nModel = 0; m_nFeatures[0] = 0; @@ -126,6 +130,6 @@ const char* GetProcessorBrand(bool bRemovePadding); const CPUInformation& GetCPUInformation(void); -void CheckCPUforSSE2(); +void CheckSystemCPU(); #endif // CPU_H diff --git a/r5dev/windows/system.cpp b/r5dev/windows/system.cpp index d72c47b0..bc248d20 100644 --- a/r5dev/windows/system.cpp +++ b/r5dev/windows/system.cpp @@ -1,4 +1,5 @@ #include "core/stdafx.h" +#include "core/init.h" #include "windows/system.h" #include "engine/host_state.h" @@ -61,14 +62,18 @@ ConsoleHandlerRoutine( case CTRL_CLOSE_EVENT: case CTRL_LOGOFF_EVENT: case CTRL_SHUTDOWN_EVENT: - if (g_pHostState) - { - g_pHostState->m_iNextState = HostStates_t::HS_SHUTDOWN; - } + + if (!g_bSdkShutdownInitiatedFromConsoleHandler) + g_bSdkShutdownInitiatedFromConsoleHandler = true; - // Give it time to shutdown properly, value is set to the max possible + if (g_pHostState) // This tells the engine to gracefully shutdown on the next frame. + g_pHostState->m_iNextState = HostStates_t::HS_SHUTDOWN; + + // Give it time to shutdown properly, this loop waits for max time // of SPI_GETWAITTOKILLSERVICETIMEOUT, which is 20000ms by default. - Sleep(20000); + while (g_bSdkInitialized) + Sleep(50); + return TRUE; }