Skip to content

[memory-leak] Dispose previous uniform buffer in SKRuntimeEffectUniforms.Reset() - #4783

Draft
github-actions[bot] wants to merge 1 commit into
mainfrom
dev/memory-leak-runtimeeffect-uniforms-reset-9df8bbe74397c9b9
Draft

[memory-leak] Dispose previous uniform buffer in SKRuntimeEffectUniforms.Reset()#4783
github-actions[bot] wants to merge 1 commit into
mainfrom
dev/memory-leak-runtimeeffect-uniforms-reset-9df8bbe74397c9b9

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

AI-generated fix — produced by the Fixer - Memory Leak agentic workflow using the memory-leak-fixer skill (focus area 0: Undisposed native handle). The fix is validated by a red→green regression test (proven failing without the fix, passing with it).

The fix

SKRuntimeEffectUniforms.Reset() replaced its owned, native ref-counted SKData buffer with a freshly-allocated one without disposing the previous buffer, leaking one native SkData allocation 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:

public void Reset ()
{
    if (data.Size == 0)
        return;

    var old = data;
    data = SKData.Create (old.Size);
    old.Dispose ();
}

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 after Reset() (deterministic, no GC needed):

# Without the fix (red):
dotnet test tests/SkiaSharp.Tests.Console/SkiaSharp.Tests.Console.csproj \
  -p:TargetFramework=net10.0 -p:TargetFrameworks=net10.0 \
  -- --filter-method "*ResetDisposesPreviousUniformBuffer*"
# => Failed: 1, Passed: 0

# With the fix (green):
# => Failed: 0, Passed: 1

Both directions verified (revert ⇒ red, re-apply ⇒ green). Neighbouring non-GPU SKRuntimeEffectTest tests 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

  • Clear framework bug, not a usage footgun — the leak is entirely inside SkiaSharp-owned managed code.
  • Empirically proven, not just statically reasoned.
  • ABI-stable: no public signature changed; the change is internal to Reset().
  • Managed C# only (binding/SkiaSharp/SKRuntimeEffect.cs + test); no generated files or externals/skia/** touched.

Areas Affected

  • SkiaSharp (core bindings)

Fixes #4782

Labels: tenet/performance, perf/memory-leak.

Generated by Fixer - Memory Leak · opus48 · 319.4 AIC · ⌖ 28 AIC · ⊞ 12K ·

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>
@github-actions github-actions Bot added partner/agentic-workflows Issues and PRs created by SkiaSharp agentic workflows. perf/memory-leak Unbounded memory growth: leaked native handles or undisposed objects. Implies tenet/performance. tenet/performance Performance related issues labels Aug 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

partner/agentic-workflows Issues and PRs created by SkiaSharp agentic workflows. perf/memory-leak Unbounded memory growth: leaked native handles or undisposed objects. Implies tenet/performance. tenet/performance Performance related issues

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

[memory-leak] SKRuntimeEffectUniforms.Reset() leaks the previous native SKData buffer

0 participants