Skip to content

fix: WMI disposal, operation lock deadlock, separate CTS#384

Merged
laurentiu021 merged 1 commit into
mainfrom
fix/wmi-disposal-lock-deadlock
May 15, 2026
Merged

fix: WMI disposal, operation lock deadlock, separate CTS#384
laurentiu021 merged 1 commit into
mainfrom
fix/wmi-disposal-lock-deadlock

Conversation

@laurentiu021

@laurentiu021 laurentiu021 commented May 15, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes WMI COM handle leaks, operation lock deadlock, and shared CTS interference.

WMI Disposal (SVC-43-45, SVC-15)

  • SystemInfoService — QueryMemory() and QueryDisks() iterated ManagementObject without using(mo). 4 foreach loops now properly dispose both the collection and each ManagementObject, preventing COM handle accumulation.
  • FixedDriveService — same fix for MSFT_PhysicalDisk enumeration.

Operation Lock Deadlock (VM-16)

  • DeepCleanupViewModel — CleanAsync() held the disk operation lock while calling ScanAsync() for post-clean rescan. ScanAsync() tried to acquire the same lock and always failed silently, leaving the user with stale data.
  • Fix: Extracted ScanCoreAsync() (lock-free inner logic). CleanAsync now calls ScanCoreAsync directly since it already holds the disk lock.

Shared CTS Interference (VM-17)

  • WindowsFeaturesViewModel — single _cts was shared between scan and toggle operations. Starting a toggle cancelled any running scan.
  • Fix: Separated into _scanCts and _toggleCts with independent lifecycle.

Build

  • 0 errors, 16 warnings (all pre-existing)
  • Tests project: 0 errors

Summary by CodeRabbit

  • Bug Fixes
    • Improved resource management for system information queries to prevent memory leaks.
    • Resolved potential deadlock during post-cleanup system scans.
    • Fixed issue where toggling Windows features could interrupt ongoing scans.

Review Change Stack

- SystemInfoService: add using(mo) + using collection in QueryMemory and
  QueryDisks (4 foreach loops — COM handle leak)
- FixedDriveService: add using(mo) + using collection in MSFT_PhysicalDisk
- DeepCleanupViewModel: extract ScanCoreAsync() without lock acquisition;
  CleanAsync calls ScanCoreAsync instead of ScanAsync (which re-acquires
  the same disk lock and always failed silently)
- WindowsFeaturesViewModel: separate _scanCts and _toggleCts so toggle
  operations do not cancel a running feature scan
- Add audit JSON files to .gitignore
@coderabbitai

coderabbitai Bot commented May 15, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR backports three targeted bug fixes for v0.48.18: WMI resource disposal in system query services, deadlock prevention in deep cleanup scan flow via method extraction, and independent cancellation control in Windows features to prevent toggling from interrupting scans.

Changes

WMI Disposal and Concurrency Control Fixes

Layer / File(s) Summary
WMI Resource Disposal Fixes
SysManager/SysManager/Services/FixedDriveService.cs, SysManager/SysManager/Services/SystemInfoService.cs
FixedDriveService and SystemInfoService now wrap ManagementObjectCollection enumeration in using statements and explicitly dispose each ManagementObject with inner using blocks across memory queries (Win32_OperatingSystem, Win32_PhysicalMemory) and disk queries (MSFT_PhysicalDisk, Win32_DiskDrive).
Deadlock Prevention in Deep Cleanup
SysManager/SysManager/ViewModels/DeepCleanupViewModel.cs
DeepCleanupViewModel extracts inner scan logic into a new ScanCoreAsync() method. ScanAsync() acquires the disk operation lock then delegates to ScanCoreAsync(), and CleanAsync() calls ScanCoreAsync() directly after cleanup to reuse scan logic without re-acquiring the lock.
Independent Cancellation Control in Windows Features
SysManager/SysManager/ViewModels/WindowsFeaturesViewModel.cs
WindowsFeaturesViewModel replaces a single shared CancellationTokenSource with separate _scanCts and _toggleCts sources so that toggling a feature does not cancel an ongoing scan. Each operation recreates its token source on start and Cancel() / Dispose() now manage both token sources.
Release Notes
CHANGELOG.md
Version 0.48.18 release entry documents the WMI disposal fixes for both services, the deadlock prevention refactor in DeepCleanupViewModel, and the cancellation isolation improvement in WindowsFeaturesViewModel.

🎯 2 (Simple) | ⏱️ ~15 minutes

Possibly Related PRs

Poem

🐰 Resources freed with careful using,
Deadlocks gone and cancels choosing,
Token split for scan and toggle,
System steady, smooth, and docile! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.18% 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 concisely and accurately summarizes the three main fixes (WMI disposal, operation lock deadlock, separate CTS), matching the changeset's primary objectives.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ 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/wmi-disposal-lock-deadlock

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

@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/WindowsFeaturesViewModel.cs`:
- Around line 22-23: The current split of _scanCts and _toggleCts allows Scan
and Toggle to run concurrently while both flip a single IsBusy flag, producing
transient incorrect idle states; change the busy tracking to an atomic ref-count
or separate busy flags and ensure they are mutated in try/finally. Specifically,
add an integer BusyCount (or two bools IsScanning/IsToggling) and replace direct
sets of IsBusy in the methods that use _scanCts and _toggleCts with
Interlocked.Increment/Decrement on BusyCount (or set/clear IsScanning and
compute IsBusy = IsScanning || IsToggling), and always decrement/clear in a
finally block so IsBusy remains true until all operations complete; update the
IsBusy getter to return BusyCount > 0 (or the OR of the two flags).
🪄 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: 1d7679dc-2bdd-4259-8f5d-dd12e9132b2c

📥 Commits

Reviewing files that changed from the base of the PR and between d25031e and 67e966e.

📒 Files selected for processing (5)
  • CHANGELOG.md
  • SysManager/SysManager/Services/FixedDriveService.cs
  • SysManager/SysManager/Services/SystemInfoService.cs
  • SysManager/SysManager/ViewModels/DeepCleanupViewModel.cs
  • SysManager/SysManager/ViewModels/WindowsFeaturesViewModel.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 (9)
CHANGELOG.md (1)

9-21: LGTM!

SysManager/SysManager/ViewModels/DeepCleanupViewModel.cs (1)

149-157: LGTM!

Also applies to: 231-231

SysManager/SysManager/ViewModels/WindowsFeaturesViewModel.cs (1)

150-154: LGTM!

Also applies to: 160-164

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

60-69: LGTM!

SysManager/SysManager/Services/SystemInfoService.cs (5)

29-48: LGTM!


52-68: LGTM!


73-84: LGTM!

Also applies to: 91-107


120-152: LGTM!


157-170: LGTM!

Comment on lines +22 to +23
private CancellationTokenSource? _scanCts;
private CancellationTokenSource? _toggleCts;

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

Add runtime busy guards to prevent overlapping scan/toggle operations.

After splitting cancellation sources, scan and toggle can now overlap, but both methods independently flip a single IsBusy flag. This can transiently report idle while one operation is still running.

💡 Suggested fix
 [RelayCommand]
 private async Task ScanAsync()
 {
+    if (IsBusy) return;
     IsBusy = true;
+    ToggleFeatureCommand.NotifyCanExecuteChanged();
     IsProgressIndeterminate = true;
     StatusMessage = "Querying Windows optional features…";
@@
     finally
     {
         IsBusy = false;
         IsProgressIndeterminate = false;
+        ToggleFeatureCommand.NotifyCanExecuteChanged();
     }
 }
@@
 [RelayCommand(CanExecute = nameof(CanToggle))]
 private async Task ToggleFeatureAsync(WindowsFeature? feature)
 {
-    if (feature == null) return;
+    if (feature == null || IsBusy) return;

Also applies to: 51-54, 102-104

🤖 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/WindowsFeaturesViewModel.cs` around lines 22
- 23, The current split of _scanCts and _toggleCts allows Scan and Toggle to run
concurrently while both flip a single IsBusy flag, producing transient incorrect
idle states; change the busy tracking to an atomic ref-count or separate busy
flags and ensure they are mutated in try/finally. Specifically, add an integer
BusyCount (or two bools IsScanning/IsToggling) and replace direct sets of IsBusy
in the methods that use _scanCts and _toggleCts with
Interlocked.Increment/Decrement on BusyCount (or set/clear IsScanning and
compute IsBusy = IsScanning || IsToggling), and always decrement/clear in a
finally block so IsBusy remains true until all operations complete; update the
IsBusy getter to return BusyCount > 0 (or the OR of the two flags).

@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 45.12195% with 45 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...ysManager/SysManager/Services/SystemInfoService.cs 53.57% 16 Missing and 10 partials ⚠️
.../SysManager/ViewModels/WindowsFeaturesViewModel.cs 0.00% 15 Missing ⚠️
...ysManager/SysManager/Services/FixedDriveService.cs 75.00% 0 Missing and 2 partials ⚠️
...ager/SysManager/ViewModels/DeepCleanupViewModel.cs 33.33% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

@laurentiu021
laurentiu021 merged commit c3b5b5c into main May 15, 2026
6 of 7 checks passed
@laurentiu021
laurentiu021 deleted the fix/wmi-disposal-lock-deadlock branch May 15, 2026 08:54
laurentiu021 added a commit that referenced this pull request May 22, 2026
- SystemInfoService: add using(mo) + using collection in QueryMemory and
  QueryDisks (4 foreach loops — COM handle leak)
- FixedDriveService: add using(mo) + using collection in MSFT_PhysicalDisk
- DeepCleanupViewModel: extract ScanCoreAsync() without lock acquisition;
  CleanAsync calls ScanCoreAsync instead of ScanAsync (which re-acquires
  the same disk lock and always failed silently)
- WindowsFeaturesViewModel: separate _scanCts and _toggleCts so toggle
  operations do not cancel a running feature scan
- Add audit JSON files to .gitignore

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

Development

Successfully merging this pull request may close these issues.

2 participants