Deadlock in Linux VST3 version when simultaneously (re)opening editor windows for two instances

Version: 1.0.7
Plugin format: VST3
Host: Bitwig Studio 3.3.4
OS: Manjaro Linux (KDE Plasma, NVIDIA, 460.32.03 drivers, but those things are likely irrelevant here)

Bitwig Studio hides plugin editor windows when the browser is opened (an important note here is that it merely unmaps the X11 window, it doesn’t call IPlugView::{attached,released}()). It will also immediately open a plugin’s editor when you insert the plugin through the browser. This means that inserting a new instance of Vital when you already have a Vital editor window open will cause the first plugin’s window to be remapped, while at the same time IEditController::createView() and IPlugView::attached() will be called for the second instance. This leads to both instances becoming completely unresponsive, and the second instance’s GUI never being drawn. This only happens when both plugins are hosted inside of the same process (i.e. when individual sandboxing is not enabled).

Steps to reproduce:

  1. Open Bitwig Studio 3.3.4 (presumably every Bitwig Studio version would be affected).
  2. Make sure that the plugin hosting mode is set to anything but ‘Individually’ in the plug-ins tab of the settings dialog.
  3. Open the arrange, and click on the little plus below the tracks to insert a new track and to open the browser to choose an instrument.
  4. Pick the VST3 version of Vital from the list to have it inserted on the channel (if both the VST2 and the VST3 version are shown, the VST3 version is the one with the blue icon).
  5. After Vital’s editor has been automatically opened, repeat steps 3 and 4 to insert another instance of Vital on a new track. Notice that the first instance’s editor window automatically gets hidden when clicking on the plus icon.
  6. Now both instances are unresponsive.

GDB backtrace from when both windows are frozen:

Thread 1 "BitwigPluginHos" received signal SIGINT, Interrupt.
0x00007f5fbcc449ba in __futex_abstimed_wait_common64 () from /usr/lib/
>>> bt
#0  0x00007f5fbcc449ba in __futex_abstimed_wait_common64 () at /usr/lib/
#1  0x00007f5fbcc3e260 in pthread_cond_wait@@GLIBC_2.3.2 () at /usr/lib/
#2  0x00007f5fbca9f47d in  () at /usr/lib/
#3  0x00007f5fbca9fb0f in  () at /usr/lib/
#4  0x00007f5fbca9f307 in XLockDisplay () at /usr/lib/
#5  0x00007f5fb9e971c9 in std::_Function_handler<void (int), juce::XWindowSystem::initialiseXDisplay()::{lambda(int)#1}>::_M_invoke(std::_Any_data const&, int&&) [clone .lto_priv.4789] () at /home/robbert/.vst3/Vital.vst3/Contents/x86_64-linux/
#6  0x00007f5fb9d1edab in juce::JuceVST3EditController::JuceVST3Editor::onFDIsSet(int) () at /home/robbert/.vst3/Vital.vst3/Contents/x86_64-linux/
#7  0x000000000042ab11 in  ()
#8  0x00000000003da7a6 in  ()
#9  0x00000000003d4703 in  ()
#10 0x00007f5fbc772b25 in __libc_start_main () at /usr/lib/
#11 0x00000000002feaaa in _start ()

Temporary workaround (for anyone reading this):

When using using Bitwig, set the VST3 version of Vital to be individually sandboxed in the ‘Per Plug-in Overrides’ section of the plugin settings dialog.