fix(linux): harden EGL texture ownership - #262
Open
nmfisher wants to merge 2 commits into
Open
Conversation
This was referenced Aug 20, 2026
nmfisher
force-pushed
the
fix/linux-egl-ownership-hardening
branch
from
August 22, 2026 12:16
8c30601 to
0498cd3
Compare
nmfisher
changed the base branch from
feat/linux-same-display-eglimage
to
develop
August 22, 2026 12:17
nmfisher
force-pushed
the
fix/linux-egl-ownership-hardening
branch
from
August 22, 2026 12:22
0498cd3 to
74169a6
Compare
nmfisher
force-pushed
the
fix/linux-egl-ownership-hardening
branch
from
August 23, 2026 08:00
74169a6 to
22e1740
Compare
Follow-up hardening motivated by multi-viewer use, where several ViewerWidgets bootstrap concurrently on Linux OpenGL and every viewer resize destroys and recreates its platform texture. - Keep the thermion_flutter_render_* raster-context capture across destroy_all_contexts. The capture describes Flutter's context, which outlives plugin-owned contexts; resetting it on a bootstrap-only teardown leaked every sibling bootstrap's GL name and could fail a sibling viewer's pending getDriverPlatform with CONTEXT_NOT_READY. The capture is now cleared only in plugin dispose and re-captured by populate() whenever Flutter's context differs. - Serialize populate() (raster thread) against release_texture() (platform thread) with a per-texture GMutex. Flutter's Linux registrar lookup hands populate() a raw pointer with no reference and no synchronization with unregistration, so a destroy issued mid-import could close the producer's DMA-BUF fd while eglCreateImageKHR was using it, and pending_ready_calls was mutated from both threads. populate() now bails on destroyed textures, and destroyed textures' GObject shells are retained until plugin teardown instead of being unreffed, so a late populate can never touch a finalized object or its mutex. All heavyweight native resources are still released eagerly. - dup() the DMA-BUF fd into the consumer texture at creation (closed on release), so producer teardown can never invalidate a concurrent import independently of the mutex. - Dispatch producer teardown by external_images ownership rather than opengl_context presence. Surface ids are per-context counters, so if both producer contexts ever coexist (backend switch without destroyContext) the old dispatch could destroy an unrelated live surface in the wrong context. Co-Authored-By: Claude <noreply@anthropic.com>
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
Follow-up ownership hardening for the Linux EGL bootstrap and DMA-BUF transport introduced by #273, rebased onto the timing-only scheduler refactor from #278.
EGLDisplayinstead of assumingrenderD128NeedsBlit/BlitToExportfor Linux Vulkan before either path marks a texture available to FlutterMulti-viewer lifecycle hardening (3a7b54f)
Follow-up commit addressing scenarios where several
ViewerWidgets bootstrap concurrently and every viewer resize destroys and recreates its platform texture:thermion_flutter_render_*raster-context capture acrossdestroy_all_contexts— it describes Flutter's context, which outlives plugin-owned contexts; resetting it on a bootstrap-only teardown leaked sibling bootstrap GL names and could fail a sibling viewer's pendinggetDriverPlatformwithCONTEXT_NOT_READY. Cleared only in plugin dispose, re-captured bypopulate()on context change.populate()(raster thread) againstrelease_texture()(platform thread) with a per-textureGMutex. Flutter's Linux registrar lookup handspopulate()a raw pointer with no reference and no synchronization with unregistration, so a destroy issued mid-import could close the producer's DMA-BUF fd duringeglCreateImageKHR, andpending_ready_callswas mutated from both threads.populate()now bails on destroyed textures.populate()can never touch a finalized object or its mutex; all heavyweight native resources are still released eagerlydup()s the DMA-BUF fd into the consumer texture so producer teardown can never invalidate a concurrent importexternal_imagesownership rather thanopengl_contextpresence — surface ids are per-context counters, so a misroute in a mixed-backend state could destroy an unrelated live surfaceIntegration with #278
This does not restore the removed native render loop or couple
FrameSchedulerback to rendering. The exported plugin handle is used only by Dart's post-render Linux texture notifier.The direct notifier now has the same Vulkan publication semantics as
markTextureFrameAvailable: any intermediate Vulkan image is copied to its exported DMA-BUF before Flutter is notified. The plugin handle is cleared before disposal so a late Dart notification cannot acquire an object whose native resources are being torn down.Validation
developflutter analyzeinthermion_flutter: clean (22e1740)thermion_fluttertest suite: 29 tests passed (22e1740)git diff --check: cleanflutter analyzeunchanged from 22e1740 (no Dart files touched);git diff --checkclean