Skip to content

fix: dispose resource leaks in NetworkSharedState, TrayIconService, MemoryTestService#347

Merged
laurentiu021 merged 1 commit into
mainfrom
fix/resource-leaks-batch
May 14, 2026
Merged

fix: dispose resource leaks in NetworkSharedState, TrayIconService, MemoryTestService#347
laurentiu021 merged 1 commit into
mainfrom
fix/resource-leaks-batch

Conversation

@laurentiu021

@laurentiu021 laurentiu021 commented May 14, 2026

Copy link
Copy Markdown
Owner

Summary

Fix 3 resource leaks identified in code review (LEAK-003, LEAK-006, LEAK-007).

Changes

  • NetworkSharedState — dispose SKTypeface on LegendTextPaint in Dispose() to release unmanaged SkiaSharp memory
  • TrayIconService — dispose icon resource stream after creating System.Drawing.Icon
  • MemoryTestService — dispose Process returned by Process.Start when launching mdsched.exe

Testing

  • Build: 0 errors
  • No behavioral changes — only resource cleanup on disposal

Closes #305, Closes #321

Summary by CodeRabbit

  • Bug Fixes
    • Resolved memory leak issues by ensuring proper disposal of system resources in memory testing operations, tray icon loading, and network state monitoring to improve application stability and performance.

Review Change Stack

…emoryTestService

- NetworkSharedState: dispose SKTypeface on LegendTextPaint to release
  unmanaged SkiaSharp memory (LEAK-003)
- TrayIconService: dispose icon resource stream after creating
  System.Drawing.Icon (LEAK-006)
- MemoryTestService: dispose Process returned by Process.Start when
  launching mdsched.exe (LEAK-007)

Closes #305, Closes #321
@coderabbitai

coderabbitai Bot commented May 14, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR fixes three resource leaks by ensuring proper disposal of unmanaged objects: a Process handle in MemoryTestService, an icon resource stream in TrayIconService, and a SkiaSharp typeface in NetworkSharedState. The changelog documents these fixes in a new 0.53.1 release.

Changes

Resource Leak Fixes

Layer / File(s) Summary
Service resource disposal
SysManager/SysManager/Services/MemoryTestService.cs, SysManager/SysManager/Services/TrayIconService.cs, SysManager/SysManager/ViewModels/NetworkSharedState.cs
MemoryTestService wraps Process.Start() in a using declaration; TrayIconService explicitly checks for null and disposes the icon stream; NetworkSharedState disposes LegendTextPaint.SKTypeface in Dispose().
Release documentation
CHANGELOG.md
New 0.53.1 release entry (dated 2026-05-14) documents the three resource leak fixes under Fixed section.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 Three leaky pipes, now sealed with care,
Process, stream, and typeface—bugs laid bare.
From disposal's hand, clean and bright,
Our memory sings: no leaks in sight!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely summarizes the main changes: fixing resource leaks in three specific services with clear mentions of affected components.
Linked Issues check ✅ Passed The PR addresses the primary coding objectives: disposing SKTypeface in NetworkSharedState [#305], disposing icon stream in TrayIconService and Process in MemoryTestService [#321]. LEAK-005 (PowerShellRunner) is noted but not fully addressed in this changeset.
Out of Scope Changes check ✅ Passed The changelog update to document version 0.53.1 reflects the resource leak fixes; all code changes directly address the linked issues without unrelated modifications.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/resource-leaks-batch

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 0% with 6 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
SysManager/SysManager/Services/TrayIconService.cs 0.00% 4 Missing ⚠️
...ysManager/SysManager/Services/MemoryTestService.cs 0.00% 1 Missing ⚠️
...anager/SysManager/ViewModels/NetworkSharedState.cs 0.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@SysManager/SysManager/ViewModels/NetworkSharedState.cs`:
- Around line 491-493: Dispose the four SolidColorPaint instances owned by
NetworkSharedState in its Dispose() method: call Dispose() (and null them) on
LegendTextPaint, LegendBackgroundPaint, TooltipTextPaint, and
TooltipBackgroundPaint in addition to disposing LegendTextPaint.SKTypeface;
ensure Dispose() is idempotent by null-checking each paint before calling
Dispose() so repeated disposals are safe (update the Dispose method where
LegendTextPaint.SKTypeface is currently disposed).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a700e5f8-1a94-4974-a6c4-0b2203f4141a

📥 Commits

Reviewing files that changed from the base of the PR and between 95a0734 and 896e3ae.

📒 Files selected for processing (4)
  • CHANGELOG.md
  • SysManager/SysManager/Services/MemoryTestService.cs
  • SysManager/SysManager/Services/TrayIconService.cs
  • SysManager/SysManager/ViewModels/NetworkSharedState.cs
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Build & unit tests
  • GitHub Check: Analyze (csharp)
🔇 Additional comments (3)
SysManager/SysManager/Services/MemoryTestService.cs (1)

83-88: LGTM!

SysManager/SysManager/Services/TrayIconService.cs (1)

93-96: LGTM!

CHANGELOG.md (1)

9-17: LGTM!

Comment on lines +491 to 493
// Dispose SKTypeface (unmanaged SkiaSharp memory) — LEAK-003
LegendTextPaint.SKTypeface?.Dispose();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

find . -name "NetworkSharedState.cs" -type f

Repository: laurentiu021/SystemManager

Length of output: 127


🏁 Script executed:

cat -n ./SysManager/SysManager/ViewModels/NetworkSharedState.cs | head -100

Repository: laurentiu021/SystemManager

Length of output: 4998


🏁 Script executed:

wc -l ./SysManager/SysManager/ViewModels/NetworkSharedState.cs

Repository: laurentiu021/SystemManager

Length of output: 131


🏁 Script executed:

tail -20 ./SysManager/SysManager/ViewModels/NetworkSharedState.cs

Repository: laurentiu021/SystemManager

Length of output: 744


🏁 Script executed:

cat -n ./SysManager/SysManager/ViewModels/NetworkSharedState.cs | sed -n '480,494p'

Repository: laurentiu021/SystemManager

Length of output: 572


🏁 Script executed:

rg "SolidColorPaint" ./SysManager/SysManager/ViewModels/NetworkSharedState.cs -B 2 -A 2

Repository: laurentiu021/SystemManager

Length of output: 2272


🏁 Script executed:

web_search
SKPaint SkiaSharp disposal IDisposable

Repository: laurentiu021/SystemManager

Length of output: 167


🌐 Web query:

SkiaSharp SKPaint Dispose IDisposable memory management

💡 Result:

SKPaint in SkiaSharp implements IDisposable and must be explicitly disposed to release unmanaged native resources promptly, preventing memory leaks especially on resource-constrained devices like mobile.[1][2][3][4] The official documentation states: "Always dispose the object before you release your last reference to the SKPaint. Otherwise, the resources it is using will not be freed until the garbage collector calls the finalizer."[1][5] SKPaint inherits from SKNativeObject, which provides Dispose to release both managed and unmanaged resources, and a protected override Dispose(bool disposing) for the dispose pattern.[1][6][2] Failing to call Dispose delays native resource cleanup until GC finalization, which is non-deterministic and can lead to higher memory usage.[7][8][3] Best practices include: - Use 'using' statements for automatic disposal: using (var paint = new SKPaint) {... }[4] - Cache and reuse SKPaint objects for repeated use (e.g., same stroke color/style), as they are lightweight and do not maintain state like SKCanvas.[6][3][4] Dispose only when no longer needed. - Avoid recreating SKPaint in hot loops; dispose explicitly after caching or when changing properties significantly.[3][4] GC will eventually finalize undisposed objects, but explicit Dispose ensures deterministic cleanup.[9][8][3] Recent issues highlight keeping objects alive during native calls with GC.KeepAlive, but disposal remains essential post-use.[10]

Citations:


🏁 Script executed:

web_search
LiveChartsCore SolidColorPaint Dispose IDisposable

Repository: laurentiu021/SystemManager

Length of output: 174


🌐 Web query:

LiveChartsCore.SkiaSharpView.Painting SolidColorPaint Dispose

💡 Result:

In LiveCharts2, LiveChartsCore.SkiaSharpView.Painting.SolidColorPaint inherits Dispose/Dispose semantics from LiveChartsCore.SkiaSharpView.Painting.SkiaPaint, and you should not treat SolidColorPaint as something you manually dispose in normal UI usage. SolidColorPaint itself is a paint wrapper that sets its color during painting (it updates an internal Skia paint’s Color in OnPaintStarted/Transitionate) and does not create/dispose any Skia shader resources the way gradient paints do [1]. Disposal behavior: - The SolidColorPaint API docs show a Dispose member (inherited from its base) described as “freeing, releasing, or resetting unmanaged resources” [2]. - In the library source, gradient paints override DisposeTask to dispose their internal shader objects (example: LinearGradientPaint disposes _shader in both Transitionate and DisposeTask), which indicates why gradient paints may need disposal if you keep them around for a long time or create many of them [3]. SolidColorPaint does not show such shader disposal logic in its implementation [1]. Practical guidance: - If you pass SolidColorPaint instances as Fill/Stroke in your chart/series, LiveCharts is expected to manage their lifecycle; creating them once and reusing them is typically preferred to repeated allocations. - Only call Dispose if you explicitly created a paint and own its lifecycle outside LiveCharts (e.g., you are dynamically creating many paints and want deterministic cleanup). Otherwise, prefer letting LiveCharts manage them. If you tell me your UI framework (WPF/WinForms/MAUI/etc.) and whether you reuse the same SolidColorPaint instance or create one per render/update, I can give more targeted advice on whether disposing is likely to matter in your scenario.

Citations:


Dispose all owned paint resources, not only the typeface.

Line 492 fixes only part of LEAK-003. NetworkSharedState owns LegendTextPaint, LegendBackgroundPaint, TooltipTextPaint, and TooltipBackgroundPaint (lines 64-67), which should be disposed in Dispose() as well. All four are SolidColorPaint instances created and reused by the class; they should be disposed when the class is disposed.

Proposed fix
     public void Dispose()
     {
         Pinger.SampleReceived -= OnSample;
         TraceMonitor.RouteCompleted -= OnRouteCompleted;
         Pinger.Stop();
         Pinger.Dispose();
         TraceMonitor.Stop();
         TraceMonitor.Dispose();
         FlushTimer?.Stop();

         // Dispose SKTypeface (unmanaged SkiaSharp memory) — LEAK-003
         LegendTextPaint.SKTypeface?.Dispose();
+        LegendTextPaint.Dispose();
+        LegendBackgroundPaint.Dispose();
+        TooltipTextPaint.Dispose();
+        TooltipBackgroundPaint.Dispose();
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Dispose SKTypeface (unmanaged SkiaSharp memory) — LEAK-003
LegendTextPaint.SKTypeface?.Dispose();
}
// Dispose SKTypeface (unmanaged SkiaSharp memory) — LEAK-003
LegendTextPaint.SKTypeface?.Dispose();
LegendTextPaint.Dispose();
LegendBackgroundPaint.Dispose();
TooltipTextPaint.Dispose();
TooltipBackgroundPaint.Dispose();
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@SysManager/SysManager/ViewModels/NetworkSharedState.cs` around lines 491 -
493, Dispose the four SolidColorPaint instances owned by NetworkSharedState in
its Dispose() method: call Dispose() (and null them) on LegendTextPaint,
LegendBackgroundPaint, TooltipTextPaint, and TooltipBackgroundPaint in addition
to disposing LegendTextPaint.SKTypeface; ensure Dispose() is idempotent by
null-checking each paint before calling Dispose() so repeated disposals are safe
(update the Dispose method where LegendTextPaint.SKTypeface is currently
disposed).

@laurentiu021
laurentiu021 merged commit e53733d into main May 14, 2026
5 checks passed
@laurentiu021
laurentiu021 deleted the fix/resource-leaks-batch branch May 14, 2026 07:00
laurentiu021 added a commit that referenced this pull request May 22, 2026
## Summary
Two fixes in one PR.

### #333 — Traceroute chart not rendering
The LiveChartsCore CartesianChart collapsed to zero height when the
parent layout didn't provide explicit vertical space. Added
MinHeight=250 to ensure the chart always has room to render.

### #334 — Speed Test HTTP values too low (500-600 vs 900+ Mbps)
Increased parallel download streams from 4 to 8 and total payload from
25 MB to 50 MB. On high-speed links (1 Gbps+), 4 streams with 6.25 MB
each couldn't saturate the connection. 8 streams with 6.25 MB each (50
MB total) provides enough concurrency to measure accurately.

## Files changed
- TracerouteView.xaml — added MinHeight=250 to chart
- SpeedTestService.cs — DownloadConnections 4→8, PayloadBytes 25→50 MB

Closes #333, Closes #334

Co-authored-by: laurentiu021 <laurentiu021@users.noreply.github.com>
laurentiu021 added a commit that referenced this pull request May 22, 2026
CHANGELOG entry was incorrectly labeled v0.28.5 — the last fix: merge
(PR #347) triggered v0.28.6. Corrects the version header.

Co-authored-by: laurentiu021 <laurentiu021@users.noreply.github.com>
laurentiu021 added a commit that referenced this pull request May 22, 2026
…emoryTestService (#347)

- NetworkSharedState: dispose SKTypeface on LegendTextPaint to release
  unmanaged SkiaSharp memory (LEAK-003)
- TrayIconService: dispose icon resource stream after creating
  System.Drawing.Icon (LEAK-006)
- MemoryTestService: dispose Process returned by Process.Start when
  launching mdsched.exe (LEAK-007)

Closes #305, Closes #321

Co-authored-by: laurentiu021 <laurentiu021@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants