Fixed crash on presenting 0 size display #698
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Description
Fixed a tricky race condition crash between the rendering thread and some other thread that is in charge of a display creation, with the following stack trace:
Motivation and Context
The crash always happens in the graphics thread during an attempt to render data, but, as a symptom, display creation (
obs_display_create), setting position, and resizing are always present near the end of logs on another thread.The problem is that display initialization comprises 3 distinct steps, and each of them is a separate call. While they happen very fast (matter of milliseconds) and mutexes are correctly locked, my research shows that it is not sufficient.
The root cause of the problem is that we create OBS displays with zero width and height, which can cause issues in certain cases due to how the underlying libraries operate.
Creating a swap chain with zero dimensions is allowed, DXGI documentation explicitly states that
The real problem is that the window's client area itself is 0x0 (common during early window creation, minimization, or certain window states). I checked this with additional logs, and it is exactly how this works in our app. In this case DXGI will create buffers with 0x0 dimensions and likely with zero size in bytes, which is certainly a straight path to undefined behavior.
So...
Summary:
There are multiple ways to fix this. Most of them require redesigning something in OBS. 😄
I've chosen the easiest one, just add a guard for dimensions and not try to render 0x0 window as it is anyway meaningless.
And finally:
As the crash is rare and unreproducible, all of this is based on guesswork and some evidence. 🔎
Fingers crossed it helps. 🤞
How Has This Been Tested?
Manually, Windows only.
Types of changes