We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 1747

Summary: Resize handling is not thread-safe in SDL 2
Product: SDL Reporter: Vladimir <libsdl-bugzilla>
Component: videoAssignee: Sam Lantinga <slouken>
Status: RESOLVED ABANDONED QA Contact: Sam Lantinga <slouken>
Severity: normal    
Priority: P2    
Version: HG 2.0   
Hardware: x86   
OS: Windows 7   

Description Vladimir 2013-03-09 05:46:05 UTC
My app uses a dedicated rendering thread, to allow it to process events while waiting for vblank.

I successfully used the following model in SDL 1.2:

- Init SDL in main thread
- Init video (SDL_SetVideoMode) in rendering thread
- Lock a mutex whenever either thread accesses global state

This worked. Window resizes were handled by asking the render thread to reinitialize graphics with the new size.

In SDL 2.0 (HG 6976:177d1dc3dba6), this approach is not working, as SDL randomly crashes after a resize due to what I assume are synchronization issues.

From my limited analysis, it looks like SDL is attempting to handle the resize message itself, in the main thread. At the same time, the rendering thread might be using the renderer object.

For the Direct3D renderer, I'm getting a hang in the rendering thread, in nvd3dum.dll, as a result of a call to SDL_RenderCopy. Stack trace follows:

> ntdll.dll!_ZwWaitForSingleObject
> ntdll.dll!_ZwWaitForSingleObject
> nvd3dum.dll!57d75c8f
> ...
> nvd3dum.dll!57d81fa3
> d3d9.dll!_CreateSurfaceLH
> d3d9.dll!_DdCreateSurfaceLH
> d3d9.dll!DdCreateSurfaceFilter
> d3d9.dll!CDriverSurface::CDriverSurface
> d3d9.dll!CSwapChain::CreateWindowed
> d3d9.dll!CSwapChain::Reset
> d3d9.dll!CBaseDevice::ResetMain
> d3d9.dll!CBaseDevice::Reset
> SDL2.dll!D3D_Reset
> SDL2.dll!D3D_ActivateRenderer
> SDL2.dll!D3D_RenderCopy
> SDL2.dll!SDL_RenderCopy

For the OpenGL renderer, I'm getting a hang in the main thread, in SDL, as a result of a call to SDL_PumpEvents. Stack trace follows:

> SDL2.dll!SDL_PrintString
> SDL2.dll!SDL_vsnprintf
> SDL2.dll!SDL_snprintf
> SDL2.dll!SDL_GetErrorMsg
> SDL2.dll!SDL_GetError
> SDL2.dll!SDL_SetError
> SDL2.dll!GL_CheckAllErrors
> SDL2.dll!GL_UpdateViewport
> SDL2.dll!SDL_RendererEventWatch
> SDL2.dll!SDL_PushEvent
> SDL2.dll!SDL_SendWindowEvent
> SDL2.dll!WIN_WindowProc
> user32.dll!_InternalCallWinProc
> user32.dll!_UserCallWinProcCheckWow
> user32.dll!_CallWindowProcAorW
> user32.dll!_CallWindowProcW
> opengl32.dll!_wglWndProc
> user32.dll!_InternalCallWinProc
> user32.dll!_UserCallWinProcCheckWow
> user32.dll!_DispatchClientMessage
> user32.dll!___fnINLPWINDOWPOS
> ntdll.dll!_KiUserCallbackDispatcher
> user32.dll!_NtUserMessageCall
> user32.dll!_RealDefWindowProcWorker
> user32.dll!_RealDefWindowProcW
> uxtheme.dll!DoMsgDefault
> uxtheme.dll!OnDwpSysCommand
> uxtheme.dll!_ThemeDefWindowProc
> uxtheme.dll!_ThemeDefWindowProcW
> user32.dll!_DefWindowProcW
> user32.dll!_InternalCallWinProc
> user32.dll!_UserCallWinProcCheckWow
> user32.dll!_CallWindowProcAorW
> user32.dll!_CallWindowProcW
> SDL2.dll!WIN_WindowProc
> user32.dll!_InternalCallWinProc
> user32.dll!_UserCallWinProcCheckWow
> user32.dll!_CallWindowProcAorW
> user32.dll!_CallWindowProcW
> opengl32.dll!_wglWndProc
> user32.dll!_InternalCallWinProc
> user32.dll!_UserCallWinProcCheckWow
> user32.dll!_DispatchClientMessage
> user32.dll!___fnDWORD
> ntdll.dll!_KiUserCallbackDispatcher
> user32.dll!_NtUserMessageCall
> user32.dll!_RealDefWindowProcWorker
> user32.dll!_RealDefWindowProcW
> uxtheme.dll!DoMsgDefault
> uxtheme.dll!OnDwpNcLButtonDown
> uxtheme.dll!_ThemeDefWindowProc
> uxtheme.dll!_ThemeDefWindowProcW
> user32.dll!_DefWindowProcW
> user32.dll!_InternalCallWinProc
> user32.dll!_UserCallWinProcCheckWow
> user32.dll!_CallWindowProcAorW
> user32.dll!_CallWindowProcW
> SDL2.dll!WIN_WindowProc
> user32.dll!_InternalCallWinProc
> user32.dll!_UserCallWinProcCheckWow
> user32.dll!_CallWindowProcAorW
> user32.dll!_CallWindowProcW
> opengl32.dll!_wglWndProc
> user32.dll!_InternalCallWinProc
> user32.dll!_UserCallWinProcCheckWow
> user32.dll!_DispatchMessageWorker
> user32.dll!_DispatchMessageW
> SDL2.dll!WIN_PumpEvents
> SDL2.dll!SDL_PumpEvents

(I presume the OpenGL one is due to it attempting to access the OpenGL context of the current thread, when there is none - the context belongs to the rendering thread.)
Comment 1 Sam Lantinga 2013-03-09 12:33:58 UTC
You should pump events on the same thread that initialized video.  That may fix the issue here.
Comment 2 Vladimir 2013-03-09 19:22:20 UTC
(In reply to comment #1)
> You should pump events on the same thread that initialized video.  That may
> fix the issue here.

I tried moving renderer initialization to the event thread.

The result:

With the Direct3D renderer, I'm now getting an SDL error after a resize: An SDL_RenderCopy call fails with the error "Reset(): INVALIDCALL"

With the OpenGL renderer, the program immediately crashes (Access Violation) at the first renderer call in the rendering thread.

I should note that I've tried doing this (initializing video in the event thread) in SDL 1.2, but ran into problems with OpenGL due to the rendering context not being associated with the right thread.
Comment 3 Sam Lantinga 2013-03-09 20:06:20 UTC
Interesting, I was of the understanding that window events come in on the thread that created the window.  Did you do something to make that work?

What happens if you do everything on a single thread?  Does it significantly affect how your application behaves with SDL 2.0?
Comment 4 Vladimir 2013-03-09 20:13:31 UTC
(In reply to comment #3)
> Interesting, I was of the understanding that window events come in on the
> thread that created the window.  Did you do something to make that work?

Well, the window is created in the main (event) thread. I call SDL_CreateWindow in the event thread, then SDL_CreateRenderer in the rendering thread.

> What happens if you do everything on a single thread?  Does it significantly
> affect how your application behaves with SDL 2.0?

Well, I imagine I wouldn't have any threading problems if I don't use threads, however then I'd have to give up the ability to handle events at a granularity finer than 16ms (assuming 60Hz refresh rate), which would be a step backwards from SDL 1.2.
Comment 5 Sam Lantinga 2013-03-09 21:43:09 UTC
Well, so what you probably want to do is make a patch for SDL_render.c that disables the event handling, and select behavior based on a hint.  If you do this you'll need to manage resetting the viewport if you need that functionality.
Comment 6 Vladimir 2013-03-09 21:50:44 UTC
OK, thanks! I'll get back to this when we're further in the dev process (unless someone beats me to it).
Comment 7 Sam Lantinga 2013-03-10 03:09:03 UTC
FYI, another option is to make use of the event timestamp which currently records when the event is enqueued, but could be changed to record when the event was delivered by the OS.

This has been a long term TODO item, but nobody has needed sub-30ms precision on the input events enough to implement it.
Comment 8 Ryan C. Gordon 2018-08-06 21:20:18 UTC
Hello, and sorry if you're getting dozens of copies of this message by email.

We are closing out bugs that appear to be abandoned in some form. This can happen for lots of reasons: we couldn't reproduce it, conversation faded out, the bug was noted as fixed in a comment but we forgot to mark it resolved, the report is good but the fix is impractical, we fixed it a long time ago without realizing there was an associated report, etc.

Individually, any of these bugs might have a better resolution (such as WONTFIX or WORKSFORME or INVALID) but we've added a new resolution of ABANDONED to make this easily searchable and make it clear that it's not necessarily unreasonable to revive a given bug report.

So if this bug is still a going concern and you feel it should still be open: please feel free to reopen it! But unless you respond, we'd like to consider these bugs closed, as many of them are several years old and overwhelming our ability to prioritize recent issues.

(please note that hundred of bug reports were sorted through here, so we apologize for any human error. Just reopen the bug in that case!)

Thanks,
--ryan.