[memory-leak] Dispose previous uniform buffer in SKRuntimeEffectUniforms.Reset() - #4783
Draft
github-actions[bot] wants to merge 1 commit into
Draft
Conversation
SKRuntimeEffectUniforms.Reset() replaced its owned, ref-counted SKData buffer with a freshly-allocated one without disposing the previous buffer, leaking a native SkData allocation on every call that only the finalizer could reclaim. Dispose the old buffer before assigning the new one. Adds a regression test that proves the previous wrapper is deregistered (disposed) immediately after Reset(). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.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.
The fix
SKRuntimeEffectUniforms.Reset()replaced its owned, native ref-countedSKDatabuffer with a freshly-allocated one without disposing the previous buffer, leaking one nativeSkDataallocation per call (reclaimed only by the finalizer, non-deterministically). This is the classic undisposed native handle pattern.The idiomatic fix (matching focus area 0's
Fix ✓: dispose the owned handle deterministically when it is replaced) disposes the old buffer before assigning the new one:The temporary local avoids the focus area's Watch out pitfalls: no field is nulled before disposal, no borrowed/same-instance handle is disposed, and
SKData.Create(→sk_data_new_uninitialized) genuinely returns a fresh owned handle, so disposing the replaced one is correct — not a double-free.Proof (red→green)
Added regression test
SKRuntimeEffectTest.Generic.ResetDisposesPreviousUniformBuffer, which captures the old buffer's native handle via reflection and asserts the wrapper is deregistered from the handle dictionary immediately afterReset()(deterministic, no GC needed):Both directions verified (revert ⇒ red, re-apply ⇒ green). Neighbouring non-GPU
SKRuntimeEffectTesttests continue to pass; the 18 GPU failures in that class are pre-existing "Failed to open X display" environmental failures unrelated to this change.Scope note
Reset().binding/SkiaSharp/SKRuntimeEffect.cs+ test); no generated files orexternals/skia/**touched.Areas Affected
Fixes #4782
Labels:
tenet/performance,perf/memory-leak.