-
Notifications
You must be signed in to change notification settings - Fork 290
Fix double disposal of ITestHostApplicationLifetime implementing IAsyncCleanableExtension #6805
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…nsions Co-authored-by: Evangelink <[email protected]>
Co-authored-by: Evangelink <[email protected]>
Evangelink
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot let's add a test so we don't regress
…nupAsync calls Co-authored-by: Evangelink <[email protected]>
Added unit tests in
Commit: 2253eaf Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
test/UnitTests/Microsoft.Testing.Platform.UnitTests/Helpers/DisposeHelperTests.cs
Outdated
Show resolved
Hide resolved
Co-authored-by: Evangelink <[email protected]>
test/UnitTests/Microsoft.Testing.Platform.UnitTests/Helpers/DisposeHelperTests.cs
Show resolved
Hide resolved
Co-authored-by: Evangelink <[email protected]>
|
Moving back to draft for manual validation. |
Pull request was converted to draft
| { | ||
| await testApplicationLifecycleCallbacks.AfterRunAsync(exitCode, testApplicationCancellationToken).ConfigureAwait(false); | ||
| await DisposeHelper.DisposeAsync(testApplicationLifecycleCallbacks).ConfigureAwait(false); | ||
| _alreadyDisposedServices.Add(testApplicationLifecycleCallbacks); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From https://learn.microsoft.com/en-us/dotnet/api/system.idisposable.dispose?view=net-10.0#remarks
If an object's Dispose method is called more than once, the object must ignore all calls after the first one. The object must not throw an exception if its Dispose method is called multiple times. Instance methods other than Dispose can throw an ObjectDisposedException when resources are already disposed.
So calling multiple times looks valid. However, DisposeHelper actually does more than dispose, and it calls IAsyncCleanableExtension.CleanupAsync.
The interface IAsyncCleanableExtension doesn't document whether double cleanup should be handled correctly or not. And it's not immediately clear why IAsyncCleanableExtension interface is needed at all. Maybe it's just because IAsyncDisposable isn't available for us in the netstandard2.0 builds?
It seems we also have zero usages of IAsyncCleanableExtension. Also xunit and TUnit don't use that interface at all.
Fix double call to IAsyncCleanableExtension::CleanupAsync method
Issue: When an MTP extension implements both
ITestHostApplicationLifetimeandIAsyncCleanableExtension, theCleanupAsyncmethod is called twice - once afterAfterRunAsyncinRunTestAppAsyncand again inDisposeServiceProviderAsync.Changes Made:
ITestHostApplicationLifetimeservices inRunTestAppAsyncusing a field_alreadyDisposedServicesDisposeServiceProviderAsyncto prevent double disposalITestHostApplicationLifetimeon lines 246-247dataConsumerwas not being added toalreadyDisposedlist (was addingserviceinstead)Technical Details:
_alreadyDisposedServicesfield to track services that have been disposed inRunTestAppAsyncRunTestAppAsyncto add eachITestHostApplicationLifetimeservice to_alreadyDisposedServicesafter disposing itRunAsyncto pass_alreadyDisposedServicestoDisposeServiceProviderAsyncDisposeServiceProviderAsyncalready has logic to skip services in thealreadyDisposedlist, preventing double disposalITestHostApplicationLifetimecheck in the service disposal conditiondataConsumerwas not being tracked inalreadyDisposedlist (line 274)DisposeHelperTests.csto verify disposal behavior and prevent regressionSecurity Summary:
No security vulnerabilities were introduced by these changes. CodeQL analysis found no issues.
Original prompt
IAsyncCleanableExtension::CleanupAsyncmethod is called twice #6181💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.