From 01d6ea6c3a075757a8f1e58fd4674eadff0c7e56 Mon Sep 17 00:00:00 2001 From: Rohit Nirmal Date: Fri, 15 Oct 2021 11:19:11 -0500 Subject: [PATCH] Call CTO2GameClientShell's destructor correctly. On Linux, the destructor is called when the program closes instead of when libCShell.so is unloaded, resulting in crashes. Instead, allocate CTO2GameClientShell on the heap when the library is loaded, then delete it in CClientMgr::TermClientShellDE. We also need to set a flag in CConsole when this happens, as PrintString incorrectly thinks i_client_shell is not null and would call OnConsolePrint from a null pointer when CClientMgr::Term calls ClientStringWhine. --- NOLF2/ClientShellDLL/TO2/GlobalsInit.cpp | 15 ++++++++++++++- runtime/client/src/clientmgr.cpp | 6 ++++++ runtime/client/src/console.cpp | 7 +++++++ runtime/client/src/console.h | 3 +++ .../client/src/sys/linux/linuxconsole_impl.cpp | 8 +++++++- runtime/client/src/sys/linux/linuxconsole_impl.h | 7 +++++++ 6 files changed, 44 insertions(+), 2 deletions(-) diff --git a/NOLF2/ClientShellDLL/TO2/GlobalsInit.cpp b/NOLF2/ClientShellDLL/TO2/GlobalsInit.cpp index b96a451c..a61f5e4d 100644 --- a/NOLF2/ClientShellDLL/TO2/GlobalsInit.cpp +++ b/NOLF2/ClientShellDLL/TO2/GlobalsInit.cpp @@ -19,5 +19,18 @@ define_holder(ILTTexInterface,g_pTexInterface); SETUP_CLIENTSHELL(); +#ifndef __LINUX define_interface(CTO2GameClientShell, IClientShell); - +#else +static CAPIInstanceDefines + global_static_impl_CTO2GameClientShell_defines_IClientShell_Default_{ + new CTO2GameClientShell, + "IClientShell" "." "Default", + IClientShell::_IClientShell_VERSION_}; + +static SStaticSearchInterface + global_static_var_search_IClientShell_CTO2GameClientShell_Default_ = { + SEARCH_MARKER_INTERFACE, SEARCH_MARKER_INT, "IClientShell", + "CTO2GameClientShell", "Default", + IClientShell::_IClientShell_VERSION_}; +#endif \ No newline at end of file diff --git a/runtime/client/src/clientmgr.cpp b/runtime/client/src/clientmgr.cpp index 2a95d4c0..0b2a4915 100644 --- a/runtime/client/src/clientmgr.cpp +++ b/runtime/client/src/clientmgr.cpp @@ -429,6 +429,12 @@ void CClientMgr::TermClientShellDE() { bm_UnbindModule(m_hShellModule); m_hShellModule = NULL; +#ifdef __LINUX + delete i_client_shell; + i_client_shell = NULL; + con_client_shell_is_gone(); +#endif + } if (m_hClientResourceModule) diff --git a/runtime/client/src/console.cpp b/runtime/client/src/console.cpp index c3f91e16..6f2f4046 100644 --- a/runtime/client/src/console.cpp +++ b/runtime/client/src/console.cpp @@ -88,6 +88,13 @@ void con_WhitePrintf(const char *pMsg, ...) va_end( marker ); } +#ifdef __LINUX +void con_client_shell_is_gone() +{ + GETCONSOLE()->ClientShellIsGone(); +} +#endif + void con_OnKeyPress(uint32 key) { if (dsi_IsConsoleEnabled ()) diff --git a/runtime/client/src/console.h b/runtime/client/src/console.h index 93050169..13b5d5b2 100644 --- a/runtime/client/src/console.h +++ b/runtime/client/src/console.h @@ -51,6 +51,9 @@ void con_DrawSmall(int nLines); void con_PrintString(CONCOLOR theColor, int filterLevel, const char *pMsg); void con_Printf(CONCOLOR theColor, int filterLevel, const char *pMsg, ...); void con_WhitePrintf(const char *pMsg, ...); +#ifdef __LINUX +void con_client_shell_is_gone(); +#endif #endif // __CONSOLE_H__ diff --git a/runtime/client/src/sys/linux/linuxconsole_impl.cpp b/runtime/client/src/sys/linux/linuxconsole_impl.cpp index 0c1fb194..d8317d83 100644 --- a/runtime/client/src/sys/linux/linuxconsole_impl.cpp +++ b/runtime/client/src/sys/linux/linuxconsole_impl.cpp @@ -687,6 +687,7 @@ CConsole::CConsole() m_bInitialized = true; m_bInitTerminate = false; + m_bClientShellIsGone = false; m_Tex = NULL; m_Font = NULL; @@ -1328,7 +1329,7 @@ void CConsole::PrintString(CONCOLOR theColor, int filterLevel, const char *pMsg) // Send the info we're using for output to the client shell so the // game code can do whatever it wants with it. - if (i_client_shell != NULL) { + if (!m_bClientShellIsGone) { CConsolePrintData PrintData; // turn the CONCOLOR into an LTRGB @@ -1473,6 +1474,11 @@ void CConsole::OnKeyPress(uint32 key) } } +void CConsole::ClientShellIsGone() +{ + m_bClientShellIsGone = true; +} + uint32 GetInterfaceSurfaceMemory() { return 0; diff --git a/runtime/client/src/sys/linux/linuxconsole_impl.h b/runtime/client/src/sys/linux/linuxconsole_impl.h index 3ebdb990..ba186f73 100644 --- a/runtime/client/src/sys/linux/linuxconsole_impl.h +++ b/runtime/client/src/sys/linux/linuxconsole_impl.h @@ -217,6 +217,11 @@ class CConsole // haven't been loaded bool m_bSaveVariablesMask; + //On Linux, the client shell is heap allocated and deleted in CClientMgr::TermClientShellDE. + //For some reason, PrintString does not correctly see this, and calls OnConsolePrint to a NULL pointer. + //Instead, check this. + bool m_bClientShellIsGone; + protected: enum EConState { @@ -430,6 +435,8 @@ class CConsole void OnKeyPress( uint32 key ); + void ClientShellIsGone(); + }; extern bool IsKeyDown(uint16 vkKey);