From 031f89946bd6a24798fc80f97bca6c0464074d1e Mon Sep 17 00:00:00 2001 From: laurentiu021 Date: Fri, 15 May 2026 09:54:43 +0300 Subject: [PATCH] fix: sync-over-async, lazy enumeration, specific catches (CQ-004, CQ-010, CQ-011) --- .gitignore | Bin 996 -> 1104 bytes CHANGELOG.md | 13 +++++++++++++ .../SysManager/Services/DeepCleanupService.cs | 12 ++++++------ .../SysManager/Services/TracerouteService.cs | 6 ++++-- .../ViewModels/ProcessManagerViewModel.cs | 4 ++-- 5 files changed, 25 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index e4ad7492297629208c789f0a58ac1bb43e86c989..ca7eae36466fcdf416fdb73fa5393629c66d5752 100644 GIT binary patch delta 116 zcmaFDet~1d6XqOVE?>tWZ`Y7`M?XiO$Y9T4y{zK=JYKFq$9Tt37tfIRAlCr@pb)62 gTd0puyk~H5s4F&Eh(wrckf)ocvtx*-zaOe@0A}7J)&Kwi delta 7 Ocmcb>@q~TD6J`JoQUhB6 diff --git a/CHANGELOG.md b/CHANGELOG.md index eaeb9b2c..89f909aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,19 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +## [0.48.11] - 2026-05-15 + +### Fixed +- **ProcessManagerViewModel (CQ-004)** — replaced sync-over-async + `GetAwaiter().GetResult()` with proper `await` inside `Task.Run` async + lambda, preventing thread pool thread blocking. +- **DeepCleanupService (CQ-010)** — replaced `Directory.GetFiles()` and + `GetDirectories()` (full array allocation) with lazy `EnumerateFiles()` + and `EnumerateDirectories()` to reduce memory pressure on large directories. +- **TracerouteService (CQ-011)** — bare `catch {}` replaced with specific + `PingException`, `SocketException`, `InvalidOperationException` catches; + subscriber error catch narrowed to `catch (Exception)`. + ## [0.48.10] - 2026-05-15 ### Fixed diff --git a/SysManager/SysManager/Services/DeepCleanupService.cs b/SysManager/SysManager/Services/DeepCleanupService.cs index e16ed9a8..b8945df2 100644 --- a/SysManager/SysManager/Services/DeepCleanupService.cs +++ b/SysManager/SysManager/Services/DeepCleanupService.cs @@ -376,10 +376,10 @@ private static IEnumerable EnumerateFiles(string root, CancellationToken while (stack.Count > 0 && !ct.IsCancellationRequested) { var cur = stack.Pop(); - string[] files = Array.Empty(); - string[] dirs = Array.Empty(); - try { files = Directory.GetFiles(cur); } catch (IOException) { } catch (UnauthorizedAccessException) { } - try { dirs = Directory.GetDirectories(cur); } catch (IOException) { } catch (UnauthorizedAccessException) { } + IEnumerable files; + IEnumerable dirs; + try { files = Directory.EnumerateFiles(cur); } catch (IOException) { continue; } catch (UnauthorizedAccessException) { continue; } + try { dirs = Directory.EnumerateDirectories(cur); } catch (IOException) { dirs = []; } catch (UnauthorizedAccessException) { dirs = []; } foreach (var f in files) yield return f; foreach (var d in dirs) stack.Push(d); } @@ -393,8 +393,8 @@ private static IEnumerable EnumerateDirectoriesDepthFirst(string root, C while (stack.Count > 0 && !ct.IsCancellationRequested) { var cur = stack.Pop(); - string[] dirs = Array.Empty(); - try { dirs = Directory.GetDirectories(cur); } catch (IOException) { } catch (UnauthorizedAccessException) { } + IEnumerable dirs; + try { dirs = Directory.EnumerateDirectories(cur); } catch (IOException) { continue; } catch (UnauthorizedAccessException) { continue; } foreach (var d in dirs) stack.Push(d); if (!string.Equals(cur, root, StringComparison.OrdinalIgnoreCase)) all.Add(cur); } diff --git a/SysManager/SysManager/Services/TracerouteService.cs b/SysManager/SysManager/Services/TracerouteService.cs index 9473bc04..76c41776 100644 --- a/SysManager/SysManager/Services/TracerouteService.cs +++ b/SysManager/SysManager/Services/TracerouteService.cs @@ -54,7 +54,9 @@ public async Task> RunAsync(string host, Cancellati } } catch (OperationCanceledException) { throw; } - catch { /* swallow per-probe errors; we report them as a timeout */ } + catch (System.Net.NetworkInformation.PingException) { /* per-probe failure; reported as timeout */ } + catch (System.Net.Sockets.SocketException) { /* per-probe failure; reported as timeout */ } + catch (InvalidOperationException) { /* per-probe failure; reported as timeout */ } } var hop = new TracerouteHop @@ -101,7 +103,7 @@ private void RaiseHopCompleted(TracerouteHop hop) foreach (var h in handlers) { try { ((Action)h).Invoke(hop); } - catch { /* swallow subscriber errors */ } + catch (Exception) { /* swallow subscriber errors to protect iteration */ } } } } diff --git a/SysManager/SysManager/ViewModels/ProcessManagerViewModel.cs b/SysManager/SysManager/ViewModels/ProcessManagerViewModel.cs index 0e454f0b..dd33cf1f 100644 --- a/SysManager/SysManager/ViewModels/ProcessManagerViewModel.cs +++ b/SysManager/SysManager/ViewModels/ProcessManagerViewModel.cs @@ -54,9 +54,9 @@ private async Task RefreshAsync() { // PERF-007: Perform snapshot, icon extraction, and description lookup // on a background thread to avoid UI freezes on slow processes. - var enriched = await Task.Run(() => + var enriched = await Task.Run(async () => { - var snapshot = _service.SnapshotAsync().GetAwaiter().GetResult(); + var snapshot = await _service.SnapshotAsync(); foreach (var p in snapshot) { p.Icon = IconExtractorService.GetProcessIcon(p.FilePath, p.Name);