Crash with multiple plugin instances using OpenGL


#1

Hi!

I have got a plugin that uses OpenGL in the GUI. Everything works well as long as there is only one plugin GUI window open.
But when I have a project that has more than one plugin window opened e.g. in Cubase 7 or Reaper, there are sporadic crashes when opening or closing that project.
This happens on different Windows 7 PCs with different graphics cards (different Intel HD graphics and ATI Radeon).
I could reproduce this with a simple modification of the JUCE audio plugin demo, where I have added just one component that uses OpenGL do draw an empty green area. (see attachment)
I tested this with the latest JUCE version.

When using a Cubase project with 2 instances of that plugin where only one GUI is open, I could open and close that project more than 20 times without problems.
When the second GUI is also open, there was always a crash after opening and closing the Cubase project less than 10 times. It seems to happen more often when more than 2 instances are open.

It could happen either when opening or when closing the project. It is always a first chance exception 0xC0000005: Access violation when writing at xxxx.
In the call stack I could see that this is somewhere in the OpenGL graphics driver (e.g. ig4icd32.dll with the Intel HD 3000).
When it happens on project opening, it crashes during the call to wglCreateContext(dc) in the constructor of OpenGLContext::NativeContext.
When it happens on project closing, it crashes during the call to wglDeleteContext(renderContext); in NativeContext::deleteRenderContext()

As this happens with different graphics cards, I assume that it is not a bug of a graphics driver.
Maybe someone can reproduce the problem and find out if this has to be fixed in JUCE or if I am doing something wrong in using the OpenGLContext.

Thanks and Best Regards,
Gregor


#2

Does no one use OpenGL in plugins here?


#3

Haven’t tried it myself…


#4

Hi Jules!

Maybe you could check my little example?

Thanks and Best Regards,
Gregor


#5

Way too busy at the moment, I’m afraid, but it sounds to me like your code is sharing something - do you have any naughty static objects in there?


#6

Yeah - I’ve noticed issues with this too.

Jules - simply adding an OpenGLRenderer to the plugin causes an issue.
It has something to do with the separate window that openGL uses. When you click close on the pluginWindow it isn’t able to get rid of the GL window (it freezes).

There might be other issues too … I also get a deadlock when I try to grab the messageManagerLock on the renderer thread. Seems to work with the Juce host, but deadlock with most other hosts (and it seems the closing issue above may be the same deadlock issue somehow).

Anyway, I’m sure you are super busy, but this would be really, really, amazing to have working :slight_smile:

Here is a stack trace that may be useful - this occurs when the audioProcessorEditor has an OpenGLContext attached to it in the normal manner. If you close the window (I think pluginWindows don’t delete, just hide maybe?), the context tries to paint, but has this issue.


#7

Hi Jules!

I am using an OpenGLContext variable in my component that is derived from OpenGLRenderer, the same way it is done in the JUCE demo application.
I have already tried to use a ScopedPointer instad, but this makes no difference.

The problem might be something thread related. wglCreateContext is called in the constructor of NativeContext, which is called from the main thread which is the same thread for all plugin instances. All further calls to the NativeContext are done from the single OpenGL Rendering threads. Deleting the NativeContext is again done from the main thread. So maybe there is some simultaneous OpenGL access from multiple threads that could cause this crash.
Any ideas on this?

Best Regards,
Gregor


#8

Yeah - I just saw it here. The context is trying to render while another thread is trying to clearContentComponent().

Need to lock the rendering during destructor.


#9

Hi!

Let me share my further research with you.
Jules, it would be great if you could give a comment on this. :slight_smile:

There have been no crashes when setting setComponentPaintingEnabled(false);
But this is not a solution for me, as I need to have this enabled!

This lead me to have a closer look at where this flag is used, which is in OpenGLContext::CachedImage::renderFrame().
One thing that I was wondering about is this part:

        if (context.renderComponents)
        {
            if (isUpdating)
            {
                paintComponent();
                mmLock = nullptr;
            }

            glViewport (0, 0, viewportArea.getWidth(), viewportArea.getHeight());
            drawComponentBuffer();
        }

After the call to paintComponent(), mmLock is set to nullptr, but further OpenGL functions are called after this lock has been released. Is this intentional?
Removing the line mmLock = nullptr; or moving it to the end of the function did not solve the problem. I was just wondering about it.

The crashes do not happen anymore, if I remove the call of paintComponent();
But this is not a solution as well. :wink:

Could it be the problem, that two different threads from two different plugin instances try to lock the message manager thread of the common plugin host?

Best Regards,
Gregor


#10

Yes! Each GL context has its own thread, so there’s no problem doing that.

Sounds to me more like a Windows-specific thing, possibly some quirk of the win32 GL functions that’s getting screwed up when multiple contexts are open. Has anyone tried multiple contexts on OSX or in an app rather than a plugin?


#11

No, this definitely happens on mac (and PC).

The situation is particularly bad on ableton (mac), where just opening a plugin with openGL enabled locks up the messageManager somehow.