OpenGL glDeleteTextures Crash

We're seeing a crash in our app sometimes when glDeleteTextures is being called from the main thread. Our stack traces look like this:

Main thread:

#0    0x00007fff8d666282 in __pthread_kill ()
#1    0x00007fff902124c3 in pthread_kill ()
#2    0x00007fff8739bb73 in abort ()
#3    0x00007fff949c7bd9 in gpusGenerateCrashLog ()
#4    0x000012340043395c in gpusKillClient ()
#5    0x00007fff949c8f73 in gpusSubmitDataBuffers ()
#6    0x0000123400003cd6 in IntelCommandBuffer::getNew(GLDContextRec*) ()
#7    0x0000123400106b35 in intelSubmitCommands ()
#8    0x00007fff94b55c52 in gleUnbindTextureObject ()
#9    0x00007fff94b23e65 in gleUnbindDeleteHashNamesAndObjects ()
#10    0x00007fff94a22766 in glDeleteTextures_Exec ()
#11    0x000000010057e5a7 in juce::OpenGLTexture::release() at /Users/cbrown/Development/bittorrent-tv/deps/third-party/juce/modules/juce_opengl/opengl/juce_OpenGLTexture.cpp:176
#12    0x000000010057e4b8 in juce::OpenGLTexture::~OpenGLTexture() at /Users/cbrown/Development/bittorrent-tv/deps/third-party/juce/modules/juce_opengl/opengl/juce_OpenGLTexture.cpp:41
#13    0x000000010057c045 in juce::OpenGLTexture::~OpenGLTexture() at /Users/cbrown/Development/bittorrent-tv/deps/third-party/juce/modules/juce_opengl/opengl/juce_OpenGLTexture.cpp:40
#14    0x000000010058ed79 in juce::OpenGLRendering::CachedImageList::CachedImage::~CachedImage() at /Users/cbrown/Development/bittorrent-tv/deps/third-party/juce/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp:102
#15    0x000000010058ec75 in juce::OpenGLRendering::CachedImageList::CachedImage::~CachedImage() at /Users/cbrown/Development/bittorrent-tv/deps/third-party/juce/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp:99
#16    0x000000010058ec4a in juce::ContainerDeletePolicy<juce::OpenGLRendering::CachedImageList::CachedImage>::destroy(juce::OpenGLRendering::CachedImageList::CachedImage*) at /Users/cbrown/Development/bittorrent-tv/deps/third-party/juce/modules/juce_opengl/../juce_gui_extra/../juce_gui_basics/../juce_graphics/../juce_core/memory/juce_ContainerDeletePolicy.h:48
#17    0x000000010058ec04 in juce::ScopedPointer<juce::OpenGLRendering::CachedImageList::CachedImage>::~ScopedPointer() at /Users/cbrown/Development/bittorrent-tv/deps/third-party/juce/modules/juce_opengl/../juce_gui_extra/../juce_gui_basics/../juce_graphics/../juce_core/memory/juce_ScopedPointer.h:100
#18    0x000000010058ebe5 in juce::ScopedPointer<juce::OpenGLRendering::CachedImageList::CachedImage>::~ScopedPointer() at /Users/cbrown/Development/bittorrent-tv/deps/third-party/juce/modules/juce_opengl/../juce_gui_extra/../juce_gui_basics/../juce_graphics/../juce_core/memory/juce_ScopedPointer.h:100
#19    0x000000010058eacc in juce::OwnedArray<juce::OpenGLRendering::CachedImageList::CachedImage, juce::DummyCriticalSection>::remove(int, bool) at /Users/cbrown/Development/bittorrent-tv/deps/third-party/juce/modules/juce_opengl/../juce_gui_extra/../juce_gui_basics/../juce_graphics/../juce_core/containers/juce_OwnedArray.h:606
#20    0x000000010059cfaf in juce::OpenGLRendering::CachedImageList::imageDataBeingDeleted(juce::ImagePixelData*) at /Users/cbrown/Development/bittorrent-tv/deps/third-party/juce/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp:161
#21    0x000000010059d09f in non-virtual thunk to juce::OpenGLRendering::CachedImageList::imageDataBeingDeleted(juce::ImagePixelData*) at /Users/cbrown/Development/bittorrent-tv/deps/third-party/juce/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp:171
#22    0x00000001003550ee in void juce::ListenerList<juce::ImagePixelData::Listener, juce::Array<juce::ImagePixelData::Listener*, juce::DummyCriticalSection, 0> >::call<juce::ImagePixelData*>(void (juce::ImagePixelData::Listener::*)(juce::ImagePixelData*), juce::TypeHelpers::ParameterType<juce::ImagePixelData*>::type) at /Users/cbrown/Development/bittorrent-tv/deps/third-party/juce/modules/juce_graphics/../juce_events/broadcasters/juce_ListenerList.h:167
#23    0x00000001002d9b5c in juce::ImagePixelData::~ImagePixelData() at /Users/cbrown/Development/bittorrent-tv/deps/third-party/juce/modules/juce_graphics/images/juce_Image.cpp:34
#24    0x00000001003b4a89 in juce::CoreGraphicsImage::~CoreGraphicsImage() at /Users/cbrown/Development/bittorrent-tv/deps/third-party/juce/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm:52
#25    0x00000001003b4745 in juce::CoreGraphicsImage::~CoreGraphicsImage() at /Users/cbrown/Development/bittorrent-tv/deps/third-party/juce/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm:49
#26    0x00000001003b4769 in juce::CoreGraphicsImage::~CoreGraphicsImage() at /Users/cbrown/Development/bittorrent-tv/deps/third-party/juce/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm:49
#27    0x00000001003abb8e in juce::ContainerDeletePolicy<juce::ImagePixelData>::destroy(juce::ImagePixelData*) at /Users/cbrown/Development/bittorrent-tv/deps/third-party/juce/modules/juce_graphics/../juce_core/memory/juce_ContainerDeletePolicy.h:48
#28    0x00000001003abb3c in juce::ReferenceCountedObjectPtr<juce::ImagePixelData>::decIfNotNull(juce::ImagePixelData*) at /Users/cbrown/Development/bittorrent-tv/deps/third-party/juce/modules/juce_graphics/../juce_core/memory/juce_ReferenceCountedObject.h:366
#29    0x0000000100355559 in juce::ReferenceCountedObjectPtr<juce::ImagePixelData>::operator=(juce::ImagePixelData*) at /Users/cbrown/Development/bittorrent-tv/deps/third-party/juce/modules/juce_graphics/../juce_core/memory/juce_ReferenceCountedObject.h:299
#30    0x00000001003553b0 in juce::ReferenceCountedObjectPtr<juce::ImagePixelData>::operator=(juce::ReferenceCountedObjectPtr<juce::ImagePixelData> const&) at /Users/cbrown/Development/bittorrent-tv/deps/third-party/juce/modules/juce_graphics/../juce_core/memory/juce_ReferenceCountedObject.h:274
#31    0x00000001002c17cf in juce::Image::operator=(juce::Image const&) at /Users/cbrown/Development/bittorrent-tv/deps/third-party/juce/modules/juce_graphics/images/juce_Image.cpp:226
#32    0x000000010053f053 in juce::StandardCachedComponentImage::releaseResources() at /Users/cbrown/Development/bittorrent-tv/deps/third-party/juce/modules/juce_gui_basics/components/juce_Component.cpp:815
#33    0x00000001003c4378 in juce::Component::setVisible(bool) at /Users/cbrown/Development/bittorrent-tv/deps/third-party/juce/modules/juce_gui_basics/components/juce_Component.cpp:532

OpenGL thread:

#0    0x00007fff8d666132 in __psynch_cvwait ()
#1    0x00007fff90210ea0 in _pthread_cond_wait ()
#2    0x00000001001f182a in juce::WaitableEvent::wait(int) const at /Users/cbrown/Development/bittorrent-tv/deps/third-party/juce/modules/juce_core/native/juce_posix_SharedCode.h:97
#3    0x00000001002a95e7 in juce::MessageManagerLock::attemptLock(juce::Thread*, juce::ThreadPoolJob*) at /Users/cbrown/Development/bittorrent-tv/deps/third-party/juce/modules/juce_events/messages/juce_MessageManager.cpp:315
#4    0x00000001002a941b in juce::MessageManagerLock::MessageManagerLock(juce::Thread*) at /Users/cbrown/Development/bittorrent-tv/deps/third-party/juce/modules/juce_events/messages/juce_MessageManager.cpp:272
#5    0x00000001002a971d in juce::MessageManagerLock::MessageManagerLock(juce::Thread*) at /Users/cbrown/Development/bittorrent-tv/deps/third-party/juce/modules/juce_events/messages/juce_MessageManager.cpp:274
#6    0x00000001005868b7 in juce::OpenGLContext::CachedImage::renderFrame() at /Users/cbrown/Development/bittorrent-tv/deps/third-party/juce/modules/juce_opengl/opengl/juce_OpenGLContext.cpp:168
#7    0x0000000100587d71 in juce::OpenGLContext::CachedImage::run() at /Users/cbrown/Development/bittorrent-tv/deps/third-party/juce/modules/juce_opengl/opengl/juce_OpenGLContext.cpp:375
#8    0x0000000100587e5c in non-virtual thunk to juce::OpenGLContext::CachedImage::run() at /Users/cbrown/Development/bittorrent-tv/deps/third-party/juce/modules/juce_opengl/opengl/juce_OpenGLContext.cpp:382
#9    0x00000001001f258e in juce::Thread::threadEntryPoint() at /Users/cbrown/Development/bittorrent-tv/deps/third-party/juce/modules/juce_core/threads/juce_Thread.cpp:101

This is on OS X (Yosemite). My instincts tell me that the call is being made when the OpenGL context isn't actually current. I don't believe our application-specific code is doing anything particular interesting here. We just have a full screen OpenGL context with some components on top.

I can try to make a minimal example app, but this crash is actually kind of rare.

I should also note that this is using a January 3rd build of JUCE. I scanned through the commit history and didn't see anything that looked relevant, but I'll definitely try this with the latest and confirm that it's still there (though it may take a while).

Any ideas?

There have been several reports on the forum lately of OpenGL crashing, however, only on Intel chipsets. So this could be a driver issue. On windows, a recent intel graphics driver update fixed OpenGL glitches in the Juce demo. 

We have a Mac Mini with an intel GPU here for testing. Is it possible for you to prepare a minimal version of your code that crashes on your computer for us to test?

I'll try to. Like I said, it's kind of rare so I don't have a good repro right now.

I can see from our stack traces though that in OpenGLRendering::CachedImageList::imageDataBeingDeleted, canUseContext() is returning true when this happens. It seems like the OpenGL context should never be active on the main thread, but for that to return true, it must have been made active at some point. Are you aware of any reasons this might happen? There are definitely no makeActive calls in our codebase, but maybe it's happening as a result of something we're doing on the main thread.

Hmm this is strange. canUseContext() will call OpenGLContext::getCurrentContext() on line 694 in juce_OpenGLContext.cpp which accesses a thread local variable which stores the thread's context. If you do not attach an OpenGLContext to the main thread then this should always be null on the main thread. To investigate the cause of your crash you might want to compile your code with  JUCE_NO_COMPILER_THREAD_LOCAL=1 and set debugger breakpoints/watchpoints in juce_ThreadLocalValue.h line 113. 

I am having a similar issue: crash in glDeleteTextures(), only on an Intel HD 3000 with Yosemite after around 35 minutes of run time, each run.

The main difference is that my call to glDeleteTextures happens in the OpenGL render thread, and after adding more debug code, it never happens in another thread.

I tried adding debug for this new rendering threading issue and, after the OpenGL Renderer is attached, I have no calls outside of the Open GL Render thread to the following:

OpengGLRendering::CachedImageList::imageDataChanged
OpengGLRendering::CachedImageList::imageDataBeingDeleted
Graphics::Graphics (const Image&)

I'm beginning to think this isn't a threading problem.

Since the application crashes approximately after the same time, could it be somehow caused by a memory leak in video reserved memory? I'm a newbie with OpenGL, and I failed to find a debugging utility to validate or invalidate this possibility.

 

Having the same crashes and freezes.
They are very occasional and happen only on OS X.
In my case they are always caused by ComponentAnimator's proxy component:


Juce Message Thread (1)Queue : com.apple.main-thread (serial)
#0    0x00007fff8777abda in __abort ()
#9    0x00007fff85bf272f in glDeleteTextures_Exec ()
#10    0x00000001000dfd61 in juce::OpenGLTexture::~OpenGLTexture() ()
#11    0x00000001000e69d8 in juce::OwnedArray<juce::OpenGLRendering::CachedImageList::CachedImage, juce::DummyCriticalSection>::remove(int, bool) ()
#12    0x0000000100064aed in juce::ImagePixelData::~ImagePixelData() ()
#13    0x00000001000c142e in juce::CoreGraphicsImage::~CoreGraphicsImage() ()
#14    0x00000001003cd210 in juce::ComponentAnimator::AnimationTask::ProxyComponent::~ProxyComponent() ()
#15    0x000000010039fa8f in juce::OwnedArray<juce::ComponentAnimator::AnimationTask, juce::DummyCriticalSection>::remove(int, bool) ()
#16    0x0000000100351fb5 in juce::ComponentAnimator::timerCallback() ()
#17    0x00000001000123ee in juce::Timer::TimerThread::callTimers() ()
#18    0x000000010001211d in juce::MessageQueue::runLoopSourceCallback(void*) ()
#19    0x00007fff88af05b1 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ ()

I think this is a known issue that I'm going to look into shortly..

Jules, was this ever fixed?

 

I've been having exactly the same issue when I try to destory an OpenGLTexture.

Sorry, still on my to-do list - will bump it up in priority!

Great, I'll keep an eye out!

 

Thanks,

Luke.

I've fixed a couple of things which I *think* are the same problem reported here - would be keen to know if they fix it for you!

Excellent!

 

I see the commit so I will give that a try this afternoon and let you know!

Jules,

The fixes you commited seem to have made it more stable (resizing areas of the plug-in which render with OpenGL now don't crash!), but I have still been able to reproduce the crash when destroying and recreating the GUI.

If it helps, it's crashing in checkGLError called while constructing a new shaderContext from createOpenGLContext().

I couldn't get it to crash at all here - do you have some code you could share that reproduces it?

I'll try and find the time to throw a demo plug-in together this afternoon for you.

Sorry to dig up an old thread, but we’re seeing some very rare crashes like this in our plugins using the latest develop JUCE. Seems to happen occasionally after long periods of use.

In our case, it looks to be caused by the destructor on a JUCE OpenGLImage, which causes a bad access after calling glDeleteTextures_Exec.

Does this happen when the editor is closed? Or just after a very long time while the editor is still open? Is there any host where this happens more often?

I was recently mucking about in the code that fixed the bug mentioned in this thread (but this only happened on closing the editor). I thought I made the fix more robust.

It seems to be most likely to happen when closing the editor (or quitting the host) after it has been open for a very long time. So far, we’ve gotten it to happen in a couple AU hosts.

Not sure if this is at all helpful, but in case it is:

I tried adding a glIsTexture(textureID) check before glDeleteTextures in OpenGLFrameBuffer::Pimpl::~Pimpl(), and now I’m getting crashes on glIsTexture if the plugin has been open long enough.

I’ll try to reproduce this tomorrow. In the meantime, I’m suspecting that my commits (e91def7, 2362ca9, aec8c36) to try to make the fix more robust may have actually introduced some kind of race condition. Can you try reverting them and see if the bug goes away? Obviously this will break rendering in premiere pro but it would be a good starting point.