From bad650042437dbec10f632f081f137a10c64bd3f Mon Sep 17 00:00:00 2001 From: ed Date: Mon, 6 Jan 2020 14:20:57 +0000 Subject: [PATCH] Added activeEditorLock to AudioProcessor to replace callbackLock when accessing its activeEditor member to prevent priority inversion issues --- .../processors/juce_AudioProcessor.cpp | 20 ++++++++++++++----- .../processors/juce_AudioProcessor.h | 11 ++++++---- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp b/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp index 9f09963478..bd40623c53 100644 --- a/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp +++ b/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp @@ -52,8 +52,12 @@ AudioProcessor::AudioProcessor (const BusesProperties& ioConfig) AudioProcessor::~AudioProcessor() { - // ooh, nasty - the editor should have been deleted before its AudioProcessor. - jassert (activeEditor == nullptr); + { + const ScopedLock sl (activeEditorLock); + + // ooh, nasty - the editor should have been deleted before its AudioProcessor. + jassert (activeEditor == nullptr); + } #if JUCE_DEBUG && ! JUCE_DISABLE_AUDIOPROCESSOR_BEGIN_END_GESTURE_CHECKING // This will fail if you've called beginParameterChangeGesture() for one @@ -803,14 +807,22 @@ void AudioProcessor::audioIOChanged (bool busNumberChanged, bool channelNumChang //============================================================================== void AudioProcessor::editorBeingDeleted (AudioProcessorEditor* const editor) noexcept { - const ScopedLock sl (callbackLock); + const ScopedLock sl (activeEditorLock); if (activeEditor == editor) activeEditor = nullptr; } +AudioProcessorEditor* AudioProcessor::getActiveEditor() const noexcept +{ + const ScopedLock sl (activeEditorLock); + return activeEditor; +} + AudioProcessorEditor* AudioProcessor::createEditorIfNeeded() { + const ScopedLock sl (activeEditorLock); + if (activeEditor != nullptr) return activeEditor; @@ -820,8 +832,6 @@ AudioProcessorEditor* AudioProcessor::createEditorIfNeeded() { // you must give your editor comp a size before returning it.. jassert (ed->getWidth() > 0 && ed->getHeight() > 0); - - const ScopedLock sl (callbackLock); activeEditor = ed; } diff --git a/modules/juce_audio_processors/processors/juce_AudioProcessor.h b/modules/juce_audio_processors/processors/juce_AudioProcessor.h index a91f1ed2ba..ba11e3131d 100644 --- a/modules/juce_audio_processors/processors/juce_AudioProcessor.h +++ b/modules/juce_audio_processors/processors/juce_AudioProcessor.h @@ -964,10 +964,13 @@ public: virtual bool hasEditor() const = 0; //============================================================================== - /** Returns the active editor, if there is one. - Bear in mind this can return nullptr, even if an editor has previously been opened. + /** Returns the active editor, if there is one. Bear in mind this can return nullptr + even if an editor has previously been opened. + + Note that you should only call this method from the message thread as the active + editor may be deleted by the message thread, causing a dangling pointer. */ - AudioProcessorEditor* getActiveEditor() const noexcept { return activeEditor; } + AudioProcessorEditor* getActiveEditor() const noexcept; /** Returns the active editor, or if there isn't one, it will create one. This may call createEditor() internally to create the component. @@ -1465,7 +1468,7 @@ private: int blockSize = 0, latencySamples = 0; bool suspended = false, nonRealtime = false; ProcessingPrecision processingPrecision = singlePrecision; - CriticalSection callbackLock, listenerLock; + CriticalSection callbackLock, listenerLock, activeEditorLock; friend class Bus; mutable OwnedArray inputBuses, outputBuses;