fix: code quality — paint leak, stable chart offset, PerformanceVM dispose#409
Conversation
…spose - CQ-M1: Dispose SkiaSharp paint objects when removing ping targets - CQ-M2: Use stable host-hash offset instead of IndexOf for chart lines - CQ-M4: PerformanceViewModel overrides Dispose
📝 WalkthroughWalkthroughThis PR fixes resource leaks and chart visualization instability across two view models. NetworkSharedState now disposes SkiaSharp paint resources when targets are removed and replaces index-dependent chart offset with stable host-hash-based offset. PerformanceViewModel adds lifecycle cleanup via a Dispose override. Changes are documented in the 0.48.27 release notes. ChangesResource Disposal and Chart Offset Stabilization
Estimated Code Review Effort🎯 2 (Simple) | ⏱️ ~12 minutes Possibly Related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning Review ran into problems🔥 ProblemsGit: Failed to clone repository. Please run the Comment |
|
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
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 253-263: DisposeSeries currently only handles
LineSeries<DateTimePoint>, so LineSeries<ObservablePoint> (used by traceroute)
is skipped and its Stroke/GeometryStroke/GeometryFill/Fill remain undisposed;
update DisposeSeries to detect any LineSeries<T> (not just DateTimePoint) —
e.g., check series.GetType().IsGenericType &&
series.GetType().GetGenericTypeDefinition() == typeof(LineSeries<>) or test for
a non-generic LineSeries base/interface — then cast the instance to a variable
(or use dynamic) and call Dispose on Stroke, GeometryStroke, GeometryFill and
Fill exactly as done for line to ensure all paint resources are disposed for
trace series as well.
🪄 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: 6f587684-0d01-4e8e-8feb-291d1077339d
📒 Files selected for processing (3)
CHANGELOG.mdSysManager/SysManager/ViewModels/NetworkSharedState.csSysManager/SysManager/ViewModels/PerformanceViewModel.cs
📜 Review details
🔇 Additional comments (3)
CHANGELOG.md (1)
9-19: LGTM!SysManager/SysManager/ViewModels/NetworkSharedState.cs (1)
341-344: LGTM!Also applies to: 384-389
SysManager/SysManager/ViewModels/PerformanceViewModel.cs (1)
545-555: LGTM!
| /// <summary>Disposes paint resources attached to a chart series.</summary> | ||
| private static void DisposeSeries(ISeries series) | ||
| { | ||
| if (series is LineSeries<DateTimePoint> line) | ||
| { | ||
| (line.Stroke as IDisposable)?.Dispose(); | ||
| (line.GeometryStroke as IDisposable)?.Dispose(); | ||
| (line.GeometryFill as IDisposable)?.Dispose(); | ||
| (line.Fill as IDisposable)?.Dispose(); | ||
| } | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE="SysManager/SysManager/ViewModels/NetworkSharedState.cs"
echo "== Series construction and dispose helper =="
rg -n 'LatencySeries.Add|TraceSeries.Add|LineSeries<|DisposeSeries\(' "$FILE"Repository: laurentiu021/SystemManager
Length of output: 452
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE="SysManager/SysManager/ViewModels/NetworkSharedState.cs"
echo "== Context around series creation (lines 150-180) =="
sed -n '150,180p' "$FILE" | cat -n
echo -e "\n== Context around disposal calls (lines 230-250) =="
sed -n '230,250p' "$FILE" | cat -n
echo -e "\n== Full DisposeSeries method (lines 253-270) =="
sed -n '253,270p' "$FILE" | cat -nRepository: laurentiu021/SystemManager
Length of output: 3338
Dispose helper skips TraceSeries paint resources.
At line 256, DisposeSeries only matches LineSeries<DateTimePoint>, but traceroute uses LineSeries<ObservablePoint> (line 168). When called at line 241, the disposal is skipped for trace series, leaving their paint resources (Stroke, GeometryStroke, GeometryFill) undisposed.
Suggested fix
private static void DisposeSeries(ISeries series)
{
- if (series is LineSeries<DateTimePoint> line)
+ if (series is LineSeries<DateTimePoint> or LineSeries<ObservablePoint>)
{
- (line.Stroke as IDisposable)?.Dispose();
- (line.GeometryStroke as IDisposable)?.Dispose();
- (line.GeometryFill as IDisposable)?.Dispose();
- (line.Fill as IDisposable)?.Dispose();
+ ((line.Stroke as IDisposable)?.Dispose();
+ (line.GeometryStroke as IDisposable)?.Dispose();
+ (line.GeometryFill as IDisposable)?.Dispose();
+ (line.Fill as IDisposable)?.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 253 -
263, DisposeSeries currently only handles LineSeries<DateTimePoint>, so
LineSeries<ObservablePoint> (used by traceroute) is skipped and its
Stroke/GeometryStroke/GeometryFill/Fill remain undisposed; update DisposeSeries
to detect any LineSeries<T> (not just DateTimePoint) — e.g., check
series.GetType().IsGenericType && series.GetType().GetGenericTypeDefinition() ==
typeof(LineSeries<>) or test for a non-generic LineSeries base/interface — then
cast the instance to a variable (or use dynamic) and call Dispose on Stroke,
GeometryStroke, GeometryFill and Fill exactly as done for line to ensure all
paint resources are disposed for trace series as well.
## Summary **Batch 8** of the QA bug fix series. ### Issue #408 — Update download no SHA256 verification Added \VerifyHashAsync\ method to \UpdateService\: - Downloads the \.sha256\ file from the same GitHub release - Computes SHA256 of the local downloaded file - Compares and returns \(Verified, ExpectedHash, ActualHash)\ - Best-effort: if \.sha256\ file is unavailable (network error), returns verified=true to not block install - Logs hash match/mismatch via Serilog ### Issue #409 — Ookla CLI no hash verification Added integrity verification to \SpeedTestService.EnsureOoklaAsync\: - Computes SHA256 of downloaded zip and logs it for audit trail - Validates the zip is not corrupt (\ZipFile.OpenRead\) - Verifies the zip contains \speedtest.exe\ - Rejects corrupt/tampered downloads with descriptive error ### Testing - Build: 0 errors Closes #408, Closes #409 Co-authored-by: laurentiu021 <laurentiu021@users.noreply.github.com>
Adds CHANGELOG entries for all 9 releases from the QA bug fix session: - **v0.28.16** — Dispose lifecycle (#395, #410) - **v0.28.17** — CTS disposal + bare catch (#396, #413) - **v0.28.18** — Input validation + null checks (#397, #398) - **v0.28.19** — JSON error handling (#400) - **v0.28.20** — Drive scanning + cache eviction + ConfigureAwait (#401, #402, #403) - **v0.28.21** — Audit logging + error messages (#405, #407) - **v0.28.22** — SHA256 verification (#408, #409) - **v0.28.23** — Service timeout + snapshot persist + traceroute DNS (#414, #415, #416) - **v0.28.24** — Accessibility (#411) 18 bugs fixed in total. Co-authored-by: laurentiu021 <laurentiu021@users.noreply.github.com>
…spose (#409) - CQ-M1: Dispose SkiaSharp paint objects when removing ping targets - CQ-M2: Use stable host-hash offset instead of IndexOf for chart lines - CQ-M4: PerformanceViewModel overrides Dispose Co-authored-by: laurentiu021 <laurentiu021@users.noreply.github.com>
Summary
Addresses MEDIUM code quality findings from the comprehensive code review.
Fixes
Files changed (3)
ViewModels: NetworkSharedState, PerformanceViewModel
Docs: CHANGELOG.md
Build
0 errors, 0 new warnings.
Summary by CodeRabbit