Skip to content

Backport: Fix GLExtensions static order of deletion bug - #50

Merged
Capostrophic merged 1 commit into
OpenMW:3.6from
patricktodd:fix/glextensions-statics
Sep 10, 2026
Merged

Capostrophic merged 1 commit into
OpenMW:3.6from
patricktodd:fix/glextensions-statics

Conversation

@patricktodd

Copy link
Copy Markdown

~GLExtensions() writes into three file-scope statics (extension set, renderer string, initialised flag). A GLExtensions object can outlive static destruction: every VertexArrayState holds a ref_ptr to it, and the VertexArrayStateManager keeps released states in the ContextData until process exit, so with vertex array objects in use the last one is deleted from exit()'s static destructors after the statics are gone, corrupting the heap and crashing in whichever static destructor frees next. Allocate the registries once and never free them.

Found while getting OpenMW to run on a 4.1 core profile context on macOS, which is where OSG ends up using VAOs.

The process crashed inside libosg's static destructors after the engine's own clean shutdown, about one run in three in my tests, never without VAOs. Guard malloc on macOS turns the heap corruption into an immediate fault at the write in ~GLExtensions.

With this change: clean exit every time, guard malloc quiet. Should be independent of anything else.

@AnyOldName3

Copy link
Copy Markdown
Member

This seems like it's suppressing a symptom of a bug rather than fixing a bug. A GLExtensions object absolutely should not outlive static destruction as it (and the classes you've listed that directly or indirectly own a ref_ptr to it) should never outlive the OpenGL context they're associated with, and that should have already been torn down before static destruction even starts.

Something's not wired up properly if these things are outliving their GL context, but it's not clear at a glance whether that would be an OSG bug or an OpenMW bug.

@magicaldave

Copy link
Copy Markdown

This appears to be a perfectly legitimate bug that got fixed upstream six years ago, so we could just backport that commit. It's not present in OpenMW's 3.6 branch, so it'd probably make more sense to just pull that in, instead.

The s_glExtensionSetList could be deleted while pointers to
GLExtension objects were still held e.g., by
VertexArrayStateManager, causing a segfault. This patch uses an
observer pointer to not access already-deleted data.

(cherry picked from commit 97f955b; the include block differs in 3.6, resolved by adding <osg/observer_ptr>)
@patricktodd
patricktodd force-pushed the fix/glextensions-statics branch from 8f794ef to 168788c Compare September 7, 2026 23:40
@patricktodd

Copy link
Copy Markdown
Author

Ah yeah they did, definitely makes more sense to pull their fix
I've replaced my commit with upstream's 97f955b cherry-picked as-is (only change: adding the observer_ptr include, since the include block differs in 3.6).

Ran the same tests with their fix on my build and it worked without issue, clean exits every time. No reason to diverge from upstream.

@patricktodd patricktodd changed the title GLExtensions: never destroy the per-context extension registries Backport: Fix GLExtensions static order of deletion bug Sep 7, 2026
@magicaldave

Copy link
Copy Markdown

I am apparently authorized to merge this although I refuse to press that specific button on this specific repository and leave said responsibility to AON - but seems legit, yea.

@Capostrophic
Capostrophic merged commit c53a6c0 into OpenMW:3.6 Sep 10, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants