This repository was archived by the owner on Sep 7, 2022. It is now read-only.
fix potential crash when spawning UIWidgetsPanels inside the Update of a MonoBehaviour #307
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.
In this PR we focus on fixing a bug that leads to crash when spawning UIWidgetsPanels inside the Update function of a MonoBehaviour:
What we fix:
When implementing UIWidgets, we heavily rely on two threads on the C++ side: (1) the main thread where the managed code (i.e., C# codes) are executed; (2) the render thread where the flutter engine is called to draw the UI elements.
Usually we cannot mess up with the two threads, e.g., changing stuffs in render thread from the main thread, which may cause undefined behaviors. However, we do such thing when calling "UIWidgetsPanel::OnEnable" where we have to do some initialization stuff, including some critical operations like reset the opengl context which is used in render thread: This operation turns out to be the root cause of the crash issue:
Assume in frame N, on the main thread we call onEnable and initialize a new UIWidgetsPanel, then it will emits rendering tasks to the render thread so that the flutter engine will draw the ui elements. Note that these tasks are emited after the rendering progress of frame N so they won't be processed in frame N. Next, in frame N+1, if we create another UIWIdgetsPanel and call its onEnable, it will first reset the current opengl context and then switch to the render thread to fetch the gfx_render_thread_id: At this time, since we have switched to the render thread, the pending rendering tasks in frame N will be also processed. However, since we have reset the opengl context, these tasks are now running with an invalid opengl context, in which the status of the underlying opengl state machine is wrong (e.g., the cached frame buffer is unloaded). Therefore a crash happens.
How we fix:
To fix this issue, we just need to guarantee that the operation to change the opengl context must happen after the pending rendering tasks for the previous frame are all finished. So we need to reorder the sequence of "reset the current opengl context" and "switch to render thread".
In this PR, we also add a new sample: UISpawnerTest for the regression tests on this issue