fix(gles): keep surface-created EGL context alive past Surface.Destroy - #362
Open
admin-else wants to merge 2 commits into
Open
admin-else wants to merge 2 commits into
admin-else wants to merge 2 commits into
Conversation
added 2 commits
September 30, 2026 17:30
On Linux the AdapterContext that backs an EGL context may be created by the
Surface instead of the Instance (Wayland, or when the detected window kind
differs from the real window's kind, e.g. an X11 window under a Wayland session).
In that case Surface.SetFail owned the context and Surface.Destroy freed it.
The Adapter, Device and Queue created from that Surface hold the same
*AdapterContext and outlive the Surface. Closing the window freed the EGL
context first; the later Device.Destroy locked a nil EGL context ("gles:
AdapterContext.Lock: nil egl context") and dereferenced the nil *gl.Context in
DeleteVertexArrays, crashing during app shutdown:
panic: runtime error: invalid memory address or nil pointer dereference
... gles.(*Device).Destroy -> gl.(*Context).DeleteVertexArrays(0x0)
Adopt ownership on the Instance when CreateSurface has to create the context.
The Instance is released after the Device and Surface, so the shared context now
lives as long as everything that uses it. Region Path B now always returns
ownsContext=false.
Adds an integration regression test that destroys a Surface sharing an adopted
context, then destroys the Device, then the Instance.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
On Linux GLES, a
Surfacethat has to create its own EGL context (Wayland, or when the detected window kind does not match the real window) owned that context and freed it inSurface.Destroy. TheAdapter,Device, andQueuecreated from that Surface share the same*AdapterContextand outlive the Surface, so closing the window freed the EGL context first and the laterDevice.Destroylocked a nil EGL context.Reproduced signature:
This crashes any app that closes a window under GLES when the context is Surface-owned.
Root cause
Instance.CreateSurfacehas two paths:AdapterContext—ownsContext=false, so the Instance (released last) frees it.AdapterContextwithownsContext=true.AdapterContext.DestroysetseglCtx=nilandgl=nil. In Path B the Surface then destroyed the context thatDevice/Queue/Adapterstill referenced. On shutdown gogpu destroys the Surface (window close), then the Device, then the Instance, so the Device hit a dead context:Lock()loggednil egl context, returned the nilgltable, andDeleteVertexArraysdereferenced nil.Fix
CreateSurfacenow adopts the Path B context on theInstance. The Instance is released after the Device and Surface, so the shared context lives as long as everything that uses it. Path B now returnsownsContext=false; theInstance.ctxfield is guarded by a mutex.This mirrors the Windows/X11 model where the context is owned by the Instance, not the Surface.
Testing
go test ./core/ ./hal/...— passgo test -tags integration ./hal/gles/— pass, including a new regression testTestSurfaceDoesNotDestroyAdoptedContextthat destroys a Surface sharing an adopted context, then the Device, then the Instance (the exact shutdown order that used to panic).go build ./...— passRelated
Follow-up to the GLES Linux AdapterContext work (FEAT-GLES-003, #332).