From 3f1f94c9d862330346e49ab964f56f425fcab10b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 18 Jun 2022 11:57:57 +0200 Subject: [PATCH] Fix segfault in `SDL_JoystickClose` on client quit Instead of closing the joysticks manually, use `SDL_QuitSubSystem(SDL_INIT_JOYSTICK)` to quit the entire subsystem, which will also close all joysticks correctly. The engine input destructor is replaced with a `Shutdown` method so we can control when it is called, i.e. before calling `SDL_Quit`, which forcefully quits all subsystems. `CJoystick::Close` is removed as we don't need to close joysticks manually anymore. --- src/engine/client/client.cpp | 1 + src/engine/client/input.cpp | 23 +++++++++-------------- src/engine/client/input.h | 3 +-- src/engine/input.h | 1 + 4 files changed, 12 insertions(+), 16 deletions(-) diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 4810efae3..a27195466 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -3351,6 +3351,7 @@ void CClient::Run() m_NetClient[i].Close(); delete m_pEditor; + m_pInput->Shutdown(); m_pGraphics->Shutdown(); // shutdown SDL diff --git a/src/engine/client/input.cpp b/src/engine/client/input.cpp index e9fd2b308..c98e6a87f 100644 --- a/src/engine/client/input.cpp +++ b/src/engine/client/input.cpp @@ -62,12 +62,6 @@ CInput::CInput() m_aEditingText[0] = 0; } -CInput::~CInput() -{ - SDL_free(m_pClipboardText); - CloseJoysticks(); -} - void CInput::Init() { m_pGraphics = Kernel()->RequestInterface(); @@ -80,6 +74,12 @@ void CInput::Init() InitJoysticks(); } +void CInput::Shutdown() +{ + SDL_free(m_pClipboardText); + CloseJoysticks(); +} + void CInput::InitJoysticks() { if(!SDL_WasInit(SDL_INIT_JOYSTICK)) @@ -167,18 +167,13 @@ CInput::CJoystick::CJoystick(CInput *pInput, int Index, SDL_Joystick *pDelegate) void CInput::CloseJoysticks() { - for(auto &Joystick : m_vJoysticks) - Joystick.Close(); + if(SDL_WasInit(SDL_INIT_JOYSTICK)) + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); + m_vJoysticks.clear(); m_pActiveJoystick = nullptr; } -void CInput::CJoystick::Close() -{ - if(SDL_JoystickGetAttached(m_pDelegate)) - SDL_JoystickClose(m_pDelegate); -} - void CInput::SelectNextJoystick() { const int Num = m_vJoysticks.size(); diff --git a/src/engine/client/input.h b/src/engine/client/input.h index 494a768a6..c0b44fa18 100644 --- a/src/engine/client/input.h +++ b/src/engine/client/input.h @@ -42,7 +42,6 @@ public: int GetHatValue(int Hat) override; bool Relative(float *pX, float *pY) override; bool Absolute(float *pX, float *pY) override; - void Close(); static int GetJoystickHatKey(int Hat, int HatValue); }; @@ -96,9 +95,9 @@ private: public: CInput(); - ~CInput(); void Init() override; + void Shutdown() override; bool ModifierIsPressed() const override { return KeyState(KEY_LCTRL) || KeyState(KEY_RCTRL) || KeyState(KEY_LGUI) || KeyState(KEY_RGUI); } bool KeyIsPressed(int Key) const override { return KeyState(Key); } diff --git a/src/engine/input.h b/src/engine/input.h index a015da55b..546a6a502 100644 --- a/src/engine/input.h +++ b/src/engine/input.h @@ -128,6 +128,7 @@ class IEngineInput : public IInput MACRO_INTERFACE("engineinput", 0) public: virtual void Init() = 0; + virtual void Shutdown() = 0; virtual int Update() = 0; virtual int VideoRestartNeeded() = 0; };