From 41ca39eab7a9c85211ae52647fb6910b2fb1c60c Mon Sep 17 00:00:00 2001 From: vsonnier Date: Wed, 1 Jun 2016 19:32:22 +0200 Subject: [PATCH] FIX audioVisOutputQueue nullptr crash --- src/demod/DemodulatorThread.cpp | 32 +++++++++++++++++++++++++------- src/demod/DemodulatorThread.h | 21 ++++++++++++--------- 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/src/demod/DemodulatorThread.cpp b/src/demod/DemodulatorThread.cpp index e7790d5..e8f4036 100644 --- a/src/demod/DemodulatorThread.cpp +++ b/src/demod/DemodulatorThread.cpp @@ -13,7 +13,9 @@ #include #endif -DemodulatorThread::DemodulatorThread(DemodulatorInstance *parent) : IOThread(), outputBuffers("DemodulatorThreadBuffers"), squelchLevel(-100), signalLevel(-100), squelchEnabled(false), cModem(nullptr), cModemKit(nullptr), iqInputQueue(NULL), audioOutputQueue(NULL), audioVisOutputQueue(NULL), threadQueueControl(NULL), threadQueueNotify(NULL) { +DemodulatorThread::DemodulatorThread(DemodulatorInstance *parent) + : IOThread(), outputBuffers("DemodulatorThreadBuffers"), squelchLevel(-100), + signalLevel(-100), squelchEnabled(false) { demodInstance = parent; muted.store(false); @@ -26,6 +28,10 @@ DemodulatorThread::~DemodulatorThread() { void DemodulatorThread::onBindOutput(std::string name, ThreadQueueBase *threadQueue) { if (name == "AudioVisualOutput") { + + //protects because it may be changed at runtime + std::lock_guard < std::mutex > lock(m_mutexAudioVisOutputQueue); + audioVisOutputQueue = (DemodulatorThreadOutputQueue *)threadQueue; } } @@ -119,7 +125,7 @@ void DemodulatorThread::run() { modemData.data.assign(inputData->begin(), inputData->end()); modemData.setRefCount(1); - AudioThreadInput *ati = NULL; + AudioThreadInput *ati = nullptr; ModemAnalog *modemAnalog = (cModem->getType() == "analog")?((ModemAnalog *)cModem):nullptr; ModemDigital *modemDigital = (cModem->getType() == "digital")?((ModemDigital *)cModem):nullptr; @@ -159,7 +165,7 @@ void DemodulatorThread::run() { } } - if (audioOutputQueue != NULL && ati && !squelched) { + if (audioOutputQueue != nullptr && ati && !squelched) { std::vector::iterator data_i; ati->peak = 0; for (data_i = ati->data.begin(); data_i != ati->data.end(); data_i++) { @@ -173,8 +179,17 @@ void DemodulatorThread::run() { ati = nullptr; } - if (ati && audioVisOutputQueue != NULL && audioVisOutputQueue->empty()) { + //At that point, capture the current state of audioVisOutputQueue in a local + //variable, and works with it with now on until the next while-turn. + DemodulatorThreadOutputQueue* localAudioVisOutputQueue = nullptr; + { + std::lock_guard < std::mutex > lock(m_mutexAudioVisOutputQueue); + localAudioVisOutputQueue = audioVisOutputQueue; + } + + if (ati && localAudioVisOutputQueue != nullptr && localAudioVisOutputQueue->empty()) { AudioThreadInput *ati_vis = audioVisBuffers.getBuffer(); + ati_vis->setRefCount(1); ati_vis->sampleRate = inp->sampleRate; ati_vis->inputRate = inp->sampleRate; @@ -230,11 +245,11 @@ void DemodulatorThread::run() { ati_vis->type = 0; } - audioVisOutputQueue->push(ati_vis); + localAudioVisOutputQueue->push(ati_vis); } - if (ati != NULL) { + if (ati != nullptr) { if (!muted.load() && (!wxGetApp().getSoloMode() || (demodInstance == wxGetApp().getDemodMgr().getLastActiveDemodulator()))) { audioOutputQueue->push(ati); } else { @@ -266,7 +281,10 @@ void DemodulatorThread::run() { outputBuffers.purge(); - if (audioVisOutputQueue && !audioVisOutputQueue->empty()) { + //Guard the cleanup of audioVisOutputQueue properly. + std::lock_guard < std::mutex > lock(m_mutexAudioVisOutputQueue); + + if (audioVisOutputQueue != nullptr && !audioVisOutputQueue->empty()) { AudioThreadInput *dummy_vis; audioVisOutputQueue->pop(dummy_vis); } diff --git a/src/demod/DemodulatorThread.h b/src/demod/DemodulatorThread.h index b95f7ac..cf3393e 100644 --- a/src/demod/DemodulatorThread.h +++ b/src/demod/DemodulatorThread.h @@ -40,8 +40,8 @@ protected: float abMagnitude(double alpha, double beta, float inphase, float quadrature); float linearToDb(float linear); - DemodulatorInstance *demodInstance; - ReBuffer outputBuffers; + DemodulatorInstance *demodInstance = nullptr; + ReBuffer outputBuffers = nullptr; std::atomic_bool muted; @@ -49,12 +49,15 @@ protected: std::atomic signalLevel; bool squelchEnabled, squelchBreak; - Modem *cModem; - ModemKit *cModemKit; + Modem *cModem = nullptr; + ModemKit *cModemKit = nullptr; - DemodulatorThreadPostInputQueue* iqInputQueue; - AudioThreadInputQueue *audioOutputQueue; - DemodulatorThreadOutputQueue* audioVisOutputQueue; - DemodulatorThreadControlCommandQueue *threadQueueControl; - DemodulatorThreadCommandQueue* threadQueueNotify; + DemodulatorThreadPostInputQueue* iqInputQueue = nullptr; + AudioThreadInputQueue *audioOutputQueue = nullptr; + DemodulatorThreadOutputQueue* audioVisOutputQueue = nullptr; + DemodulatorThreadControlCommandQueue *threadQueueControl = nullptr; + DemodulatorThreadCommandQueue* threadQueueNotify = nullptr; + + //protects the audioVisOutputQueue dynamic binding change at runtime (in DemodulatorMgr) + mutable std::mutex m_mutexAudioVisOutputQueue; };