SDL_TextureLock Multithreads = Segmentation Fault on random Systems

I’m using A STREAMING texture that I LOCK/Update/UNLOCK in a separate thread to the main thread.

This seems to work fine except on random Systems it causes a segmentation fault.

I have three systems (all with SDL2 2.0.8)

1 x Ubuntu 18.04
2 x Ubuntu 18.04
3 x Windows 10

The application works correctly on 1 & 3 but fails on 2.

If I copy the working app and libraries from system 1 to system 2 the app still breaks on system 2.

If I copy the broken apps and libraries from system 2 to system 1 it works fine on system 1.

Stepping through the code…

Originally : After I successfully lock the texture it faults on a call to : SDL_RenderSetClip() in the main thread! Which is called when the GUI detects a window resize.

Update : I downloaded the SDL source and compiled that with debug support and re-ran the application:

As a result the code now breaks at the actual problem location:

while(1)
{
    SDL_LockTexture(t, NULL, &pixels, &pitch); // succeeds
    if (pixels == NULL) fprintf(stderr, "Cannot lock texture!\n");
    // UpdateEmulationWindow(pixels);
    SDL_UnlockTexture(t); // Faults here but only after a window resize;
    MyDelay(17); // 17msecs
}

So the problem is the UnlockTexture is failing. Not sure why this only fails during a window resize. Full screen toggling is OK but not resizing. Also this texture is not been rendered to any window. There is no RenderCopy or RenderPesent.

If I don’t lock the texture it all works fine expect but of course I can’t update the contents of the texture.

What should I look for next?

At this point I’m suspecting differences in the graphics cards!!!

That’s probably what it is.

Messing with graphics assets on a thread other than the on in which they were created is undefined behavior. As Raymond Chen has pointed out in the past, undefined behavior means any possible consequence can result, including appearing to work as expected, which is exactly what you’re seeing here: it works fine on some systems but not on others. Bottom line: you just shouldn’t be doing this.

1 Like

I’m pretty sure I’ve complied with the SDL threading requirements and have restricted access to every asset from the same thread.

The thread that creates the texture is the only thread that accesses the texture.

My stepping through the debugger verifies that it still is in the same thread. So I think I’m good.

Stepping through the SDL2 code I can see this is finally handled by GL_UnlockTexture/GL_UpdateTexture. I’m haven’t specified GL so I’m surprised the GL renderer is handling this. However that is probably normal!

  • List item

You’re essentially doing OpenGL stuff on a thread other than the one the OpenGL context was created on. OpenGL contexts can only be active on one thread at a time, by making them “current” whenever they’re going to be used on a thread. Making an OpenGL context current on one thread makes it unusable on others. What you’re trying to do is undefined behavior and will only work on some systems, with some hardware, with some driver versions, some of the time.

Applications that access OpenGL directly can get around the single thread at a time limitation by making a separate OpenGL context on the second thread and sharing the texture between them, but apparently a lot of OpenGL drivers hate this. Usually people load and prepare the data on a second thread, but then do the OpenGL calls to pass the data to the GPU on the same thread as all the other OpenGL calls. Maybe you could lock/unlock the texture on your main thread, and pass a pointer to its memory to your second thread?

That’s what I ended up doing. I post events to the main thread to lock and unlock the texture now. The secondary thread just does the pixel manipulations. All fixed!