View Issue Details

IDProjectCategoryView StatusLast Update
0008550ardourbugspublic2021-02-26 18:13
ReporterCTS Assigned Tox42  
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionfixed 
PlatformArchOSLinuxOS Version(any)
Product Version6.5 
Summary0008550: Ardour crashes when opening generic UI controls for linux VST3
DescriptionSegmentation fault when viewing plugin parameters in the generic plugin UI on JUCE-based VST3 plugins on Linux.

Secondary issue which might be related is that I've noticed these same plugins that crash also have very poor (unusable) graphics performance for their custom UI. Sliders take a few seconds to update their position, CPU usage is very high etc.

These issues are present on every VST3 I build on Linux using the JUCE framework, so I honestly don't know if it's an Ardour, JUCE or me problem. However, affected plugins run fine in Carla & Reaper. Also, I've built and used these same plugins in Ardour on Mac with no problems.
Steps To ReproduceUsing JUCE AudioPluginExample

Build plugin with cmake:
```
git clone https://github.com/juce-framework/JUCE.git
cd JUCE
cmake . -B cmake-build -DJUCE_BUILD_EXAMPLES=ON -DJUCE_BUILD_EXTRAS=ON
cmake --build cmake-build --target AudioPluginExample_VST3
cp -r cmake-build/examples/CMake/AudioPlugin/AudioPluginExample_artefacts/VST3/Audio\ Plugin\ Example.vst3/ ~/.vst3/Audio\ Plugin\ Example.vst3
```

Then, in Ardour:

1. Open Ardour, add the plugin to a track without opening GUI
2. Open the plugin generic GUI controls -- no problem
3. Close generic controls, open custom plugin GUI -- no problem
4. Close plugin GUI, attempt to re-open generic plugin controls -- Ardour immediately seg faults every time.

It only seems to happen when opening the generic control AFTER having open & closed the plugin's custom UI.
TagsNo tags attached.

Activities

CTS

2021-01-24 00:42

reporter   ~0025455

GDB says the following:

Thread 1 "ArdourGUI" received signal SIGSEGV, Segmentation fault.
0x0000555556859b62 in VST3X11Runloop::event (source=0x555558f141d0, condition=G_IO_IN, data=0x555559367018) at ../gtk2_ardour/vst3_x11_plugin_ui.cc:69
69 handler->onFDIsSet (g_io_channel_unix_get_fd (source));

x42

2021-01-24 01:32

administrator   ~0025456

is this 6.5.0? If so, perhaps this was meanwhile fixed in https://github.com/ardour/ardour/commit/bbc54873aebeecf10571540963a6fdebebc36ab6

CTS

2021-01-24 01:55

reporter   ~0025458

6.5.163 - I built from master branch today and am trying to debug it with my limited cpp skills. I'll take a look at that commit and see if I find anything that might have been missed! One other important detail that I missed is that the message "PluginWindow deleted for ..." is printed right when I click "Edit with generic controls". Seems like maybe the window is deleted and then that onFDIsSet thing tries to access it? I'll poke around...

CTS

2021-01-24 02:13

reporter   ~0025459

I think I have some sense of what is happening. When I close the plugin's custom UI, the VSTPluginUI instance is not destroyed. I can also make Ardour crash the same way by doing this:

1. Add the plugin
2. Open the plugin UI, close the plugin UI
3. Delete the plugin from the track
4. Re-add the same plugin from the track --> CRASH!

Same output right when I re-add the plugin:
"PluginWindow deleted for 0x555559368af0"

So I think maybe the PluginWindow is not deleted when it should be, and then something goes weird when we try to recreate it and end up deleting it instead...

I wonder if this is related to me using a tiling window manager (i3wm), would that not send some expected signal when closing the window or something? Bit outta my depth here!!!

x42

2021-01-24 02:18

administrator   ~0025460

The plugin window is kept around when you close the GUI. It is destroyed when you show the generic UI instead, or when you remove the plugin.

> 4. Re-add the same plugin from the track --> CRASH!

That smells like static global variables shared between plugin instances.
That might also explain why it's fine in Carla. where plugins are all process separated.

--
It's odd though there are a lot of JUCE based plugins known to work fine with Ardour.

x42

2021-01-24 02:19

administrator   ~0025461

PS. Disabling Preferences > Plugins > Automatically open the plugin GUI when adding a new plugin may help to investigate

CTS

2021-01-24 02:43

reporter   ~0025462

Got it, yes creating multiple instances of the plugin and deleting some of them causes crashing too - so sounds like you are on the money. I'll comb through the plugin code and bounce this over to the juce forums.

Thanks!

CTS

2021-01-25 00:53

reporter   ~0025466

Hey so I did some more investigating and I think this has something to do with registering and unregistering event handlers. I noticed that the JUCE plugins actually call registerEventHandler more than once when opening the GUI. The unregisterEventHandler method however, assumes that there is only a single FileDescriptor, EventHandler pair in the _event_handlers unordered_map. In fact, there are at least 2 FileDescriptors matching the same event handler for JUCE plugins - I have no idea why. I got things working a little more consistently by changing the implementation of unregisterEventHandler to this:

```
    tresult unregisterEventHandler (Linux::IEventHandler* handler) SMTG_OVERRIDE
    {
        if (!handler) {
            return kInvalidArgument;
        }
                auto result = kResultFalse;
                std::vector<boost::unordered_map<FileDescriptor, EventHandler>::iterator> to_erase;

        Glib::Threads::Mutex::Lock lm (_lock);
        for (boost::unordered_map<FileDescriptor, EventHandler>::iterator it = _event_handlers.begin (); it != _event_handlers.end (); ++it) {
            if (it->second._handler == handler) {
                g_source_remove (it->second._source_id);
                g_io_channel_unref (it->second._gio_channel);
                        to_erase.push_back(it);
                //_event_handlers.erase (it);
                result = kResultTrue;
            }
        }
        for (auto& it : to_erase) {
            _event_handlers.erase(it);
        }
        return result;
        }
```

That more or less got things working for the JUCE demo plugin. I'm still having issues with some other JUCE VST3 plugins crashing when opening/closing GUI windows, but at least the useless JUCE demo plugin works now!

So that being said - am I right in thinking this is still more of a JUCE problem than an Ardour problem? Not sure why they would need to be registering the same event handler under multiple different file descriptors.

I also found that the JUCE code that acquires these file descriptors may or may not be an example of a static global variable here:
https://github.com/juce-framework/JUCE/blob/383a4232f095727dc6178ead953e49e12befa072/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp#L80
which is used to register the event handlers here:
https://github.com/juce-framework/JUCE/blob/383a4232f095727dc6178ead953e49e12befa072/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp#L1226

That seemed kind of suspicious to my not-particularly-well-trained eye.
I'll ask about that on the JUCE forums but thought I'd mention it here since it's what seems to be leading to the multiple calls to registerEventHandler.

x42

2021-01-25 01:17

administrator   ~0025468

Nice, find. I've reworked your change a bit (currently Ardour still uses C++98, no C++11 "auto" allowed):
https://github.com/Ardour/ardour/commit/35552abc4d060f60cb60e9c1e9be61b1693f1d14

It seems indeed an odd choice of JUCE here.

CTS

2021-01-25 02:35

reporter   ~0025470

Amazing thanks, that commit works very well over here!

I also found another edge case - a little further off-the-happy-path:
1. Add 2 instances of a JUCE plugin to a track
2. Open both GUIs
3. While GUIs are open, try to click "Open generic plugin controls" for one of the plugins -- CRASH

Another way to achieve the same thing:
1. Add 2 instances of the same JUCE plugin
2. Open the GUI for 1 of them
3. Close the GUI
4. Click "Open generic plugin controls" for the second one -- CRASH

Linux VST3 support is very new to both JUCE and Ardour it appears - both adding it within the last 12 months. I'll keep trying to break it and report what I find - I think having robust VST3 support between Ardour and JUCE plugins is really important in encouraging more plugin developers to provide Linux builds. I also find Ardour to be an excellent plugin testing host due to the lack of process isolation.

CTS

2021-02-26 08:45

reporter   ~0025557

Hey there - I just made a PR with a change that (so far for me) appears to completely fix this issue. I haven't been able to crash Ardour with JUCE plugin UIs with this change.

More details here:
https://github.com/Ardour/ardour/pull/598

Issue History

Date Modified Username Field Change
2021-01-23 21:16 CTS New Issue
2021-01-24 00:42 CTS Note Added: 0025455
2021-01-24 01:32 x42 Note Added: 0025456
2021-01-24 01:55 CTS Note Added: 0025458
2021-01-24 02:13 CTS Note Added: 0025459
2021-01-24 02:18 x42 Note Added: 0025460
2021-01-24 02:19 x42 Note Added: 0025461
2021-01-24 02:43 CTS Note Added: 0025462
2021-01-25 00:53 CTS Note Added: 0025466
2021-01-25 01:17 x42 Note Added: 0025468
2021-01-25 01:17 x42 Assigned To => x42
2021-01-25 02:35 CTS Note Added: 0025470
2021-02-26 08:45 CTS Note Added: 0025557
2021-02-26 18:13 CTS Status new => closed
2021-02-26 18:13 CTS Resolution open => fixed