From 530fc9130a8359afbdb3fd0d30deab9ef90e87dd Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Fri, 19 Nov 2021 23:39:18 +0100 Subject: [PATCH] Fix a deadlock in GPIO monitor --- libnymea-gpio/gpio.cpp | 1 + libnymea-gpio/gpiomonitor.cpp | 17 +++++------------ libnymea-gpio/gpiomonitor.h | 4 +--- 3 files changed, 7 insertions(+), 15 deletions(-) diff --git a/libnymea-gpio/gpio.cpp b/libnymea-gpio/gpio.cpp index 28a0e2d..596251a 100644 --- a/libnymea-gpio/gpio.cpp +++ b/libnymea-gpio/gpio.cpp @@ -139,6 +139,7 @@ Gpio::Gpio(int gpio, QObject *parent) : m_direction(Gpio::DirectionInvalid), m_gpioDirectory(QDir(QString("/sys/class/gpio/gpio%1").arg(QString::number(gpio)))) { + qRegisterMetaType(); } diff --git a/libnymea-gpio/gpiomonitor.cpp b/libnymea-gpio/gpiomonitor.cpp index e1ee24e..534f319 100644 --- a/libnymea-gpio/gpiomonitor.cpp +++ b/libnymea-gpio/gpiomonitor.cpp @@ -81,8 +81,8 @@ GpioMonitor::GpioMonitor(int gpio, QObject *parent) : m_gpioNumber(gpio) { // Inform about the thread status - connect(this, &GpioMonitor::started, this, &GpioMonitor::onThreadStarted, Qt::DirectConnection); - connect(this, &GpioMonitor::finished, this, &GpioMonitor::onThreadFinished, Qt::DirectConnection); + connect(this, &GpioMonitor::started, this, &GpioMonitor::onThreadStarted); + connect(this, &GpioMonitor::finished, this, &GpioMonitor::onThreadFinished); } /*! Destroys and unexports the Gpio. */ @@ -130,7 +130,6 @@ void GpioMonitor::setActiveLow(bool activeLow) /*! Returns the current value of the Gpio. */ Gpio::Value GpioMonitor::value() { - QMutexLocker valueLocker(&m_valueMutex); return m_value; } @@ -140,9 +139,8 @@ bool GpioMonitor::enabled() const return m_enabled; } -void GpioMonitor::setValue(Gpio::Value value) +void GpioMonitor::onValueChanged(Gpio::Value value) { - QMutexLocker valueLocker(&m_valueMutex); m_value = value; switch (m_value) { @@ -241,11 +239,8 @@ void GpioMonitor::run() // Notify the main thread about the interrupt readStream >> valueString; - if (valueString == "0") { - setValue(Gpio::ValueLow); - } else { - setValue(Gpio::ValueHigh); - } + Gpio::Value value = valueString == "1" ? Gpio::ValueHigh : Gpio::ValueLow; + QMetaObject::invokeMethod(this, "onValueChanged", Qt::QueuedConnection, Q_ARG(Gpio::Value, value)); } } @@ -280,7 +275,6 @@ bool GpioMonitor::enable() return false; } - QMutexLocker locker(&m_stopMutex); m_stop = false; // Everything looks good, lets start the poll thread and inform about the result @@ -294,6 +288,5 @@ void GpioMonitor::disable() qCDebug(dcGpio()) << "Disabling gpio monitor"; // Stop the thread if not already disabled QMutexLocker locker(&m_stopMutex); - if (m_stop) return; m_stop = true; } diff --git a/libnymea-gpio/gpiomonitor.h b/libnymea-gpio/gpiomonitor.h index a960244..da7c274 100644 --- a/libnymea-gpio/gpiomonitor.h +++ b/libnymea-gpio/gpiomonitor.h @@ -62,14 +62,11 @@ private: bool m_activeLow = true; bool m_enabled = false; - // Thread stuff - QMutex m_valueMutex; Gpio::Value m_value = Gpio::ValueInvalid; QMutex m_stopMutex; bool m_stop = false; - void setValue(Gpio::Value value); void setEnabled(bool enabled); protected: @@ -82,6 +79,7 @@ signals: private slots: void onThreadStarted(); void onThreadFinished(); + void onValueChanged(Gpio::Value value); public slots: bool enable();