From 538b448ae0ac1b9c64af2bbf6ae354346df7a3ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beat=20K=C3=BCng?= Date: Wed, 27 Jan 2021 09:56:32 +0100 Subject: [PATCH] joystick: fix crash on app exit This fixes a pure virtual method call exception during exit when a joystick is connected. The problem was that ~Joystick() waited for the thread to exit, while the thread called the virtual method _close(). But at this point the destructor of the derived class (JoystickSDL in my case) was already called. To resolve the problem a separate stop() method is added that is called before deleting the object. --- src/Joystick/Joystick.cc | 9 ++++++++- src/Joystick/Joystick.h | 6 ++++-- src/Joystick/JoystickManager.cc | 1 + 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/Joystick/Joystick.cc b/src/Joystick/Joystick.cc index 36f9d82..e0b1d10 100644 --- a/src/Joystick/Joystick.cc +++ b/src/Joystick/Joystick.cc @@ -121,10 +121,17 @@ Joystick::Joystick(const QString& name, int axisCount, int buttonCount, int hatC connect(_multiVehicleManager, &MultiVehicleManager::activeVehicleChanged, this, &Joystick::_activeVehicleChanged); } -Joystick::~Joystick() +void Joystick::stop() { _exitThread = true; wait(); +} + +Joystick::~Joystick() +{ + if (!_exitThread) { + qWarning() << "Joystick thread still running!"; + } delete[] _rgAxisValues; delete[] _rgCalibration; delete[] _rgButtonValues; diff --git a/src/Joystick/Joystick.h b/src/Joystick/Joystick.h index e42cf0d..e0b3876 100644 --- a/src/Joystick/Joystick.h +++ b/src/Joystick/Joystick.h @@ -18,6 +18,7 @@ #include "QGCLoggingCategory.h" #include "Vehicle.h" #include "MultiVehicleManager.h" +#include Q_DECLARE_LOGGING_CATEGORY(JoystickLog) Q_DECLARE_LOGGING_CATEGORY(JoystickValuesLog) @@ -53,7 +54,7 @@ class Joystick : public QThread public: Joystick(const QString& name, int axisCount, int buttonCount, int hatCount, MultiVehicleManager* multiVehicleManager); - ~Joystick(); + virtual ~Joystick(); typedef struct Calibration_t { int min; @@ -137,6 +138,7 @@ public: void setFunctionAxis(AxisFunction_t function, int axis); int getFunctionAxis(AxisFunction_t function); + void stop(); /* // Joystick index used by sdl library @@ -263,7 +265,7 @@ protected: uint8_t*_rgButtonValues = nullptr; - bool _exitThread = false; ///< true: signal thread to exit + std::atomic _exitThread{false}; ///< true: signal thread to exit bool _calibrationMode = false; int* _rgAxisValues = nullptr; Calibration_t* _rgCalibration = nullptr; diff --git a/src/Joystick/JoystickManager.cc b/src/Joystick/JoystickManager.cc index 530b057..0cba191 100644 --- a/src/Joystick/JoystickManager.cc +++ b/src/Joystick/JoystickManager.cc @@ -38,6 +38,7 @@ JoystickManager::~JoystickManager() { QMap::iterator i; for (i = _name2JoystickMap.begin(); i != _name2JoystickMap.end(); ++i) { qCDebug(JoystickManagerLog) << "Releasing joystick:" << i.key(); + i.value()->stop(); delete i.value(); } qDebug() << "Done";