Macosx: ScopedLock in processor.getActiveEditor() hangs

Strange issue here
JUCE v7.0.5
getActiveEditor hangs in the standalone version of my plugin on macosx
When I disable the ScopedLock there, the issue is gone.
I do not use ScopedLocks myself.
I fixed it by adding a bool in processor that is set by the editor itself,
but I’m just curious how getActiveEditor can get into a hanging state at all.
The problem occurs on macos, but not on iOS.

AudioProcessorEditor* AudioProcessor::getActiveEditor() const noexcept
{
    const ScopedLock sl (activeEditorLock);
    return activeEditor;
}

it happens during startup when the editor is still not visible: now I’d expect that I’d just get a nullptr in that phase, which is true, because if I remove the ScopedLock, the nullptr is delivered and my code reacts appropiately.

It’s difficult to say without knowing where the other thread is stuck. We can see that the audio thread is stuck on the activeEditorLock, but it will have taken a few other locks too at that point.

At the point of the deadlock, is any other thread (most likely the message thread) also waiting on a lock? If so, please post the stack trace of that thread.

1 Like

thanks sofar!
I’ll post the stacktrace asap.
I expect a problem that is induced by setting up the audiodevice manager in the editor.

to the right you see my code to create my devicemanager component.

in stack 22 createEditorifNeeded, the ScopedLock on activeEditor is set…
I create my devicemanager only once during editor setup.

It looks like:

  • Message thread takes the activeEditorLock when creating the editor, then takes the CoreAudio lock when creating the audio device panel.
  • Audio thread takes the CoreAudio lock during processing, then takes the activeEditorLock to find out whether an editor is available.

You’ll need to avoid doing one of those things, so either:

  • Avoid getting the active editor inside processBlock, and use some other mechanism (maybe the editor can pull information from the processor, rather than having the processor push information to the editor), or
  • Avoid creating an AudioDeviceSelectorComponent (or otherwise interacting with CoreAudio) while holding the activeEditorLock (i.e. when creating or destroying the editor). Maybe you can create the SelectorComponent on-demand after opening the editor, for example.
1 Like

ok… I didnt realise ScopeLock can actually lead to deadlocks.
If assume that only 2 functions invoke the editor lock, that means createEditorifNeeded and myown functions in the audiothread. So I skip my locks untill the editor ( and the devicemanager in it ) is ready.
I have 3 sliders that are attached to the tree, and gestures in the audio thread go via the tree. That is the safe prefered method I guess.
But I also have a few other things that are just cumbersome to implement via the tree and gestures.
I use therefore getActiveEditor() and sofar this didnt cause any problems in the wild, as long as I did only atomic stuff. LIke said, all my parameter communication is via the tree.
Is there another approved processor->editor communication method other then gestures? I now only set a few dedicated vars in the editor, that are read on timer interrupt.

The problem here is the call to getActiveEditor, because that takes the active editor lock. Your editor already takes a reference to its corresponding processor in its constructor, so have the editor query the values from the processor in a timer managed by the editor.

1 Like

ok, that makes sense!
I realise now that I allready used this method too, but since I got no errors either way, both the locking and non-locking way looked too much alike.
For some actions, this onTimer “editor reads processor” stuff looks a bit elaborate. But if it is the only non-locking way: ok. then that is the way.

EDIT:
I’d recommend to make getActiveEditor() deprecated. that would be more clear.