-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
Fixes race condition on captive scoped services #53325
Conversation
Tagging subscribers to this area: @eerhardt, @maryamariyan Issue DetailsFixes: #52221 TODO:
|
@maryamariyan I think you have linked the wrong issue. Should be #52863? |
...s/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitResolverBuilder.cs
Outdated
Show resolved
Hide resolved
...s/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitResolverBuilder.cs
Outdated
Show resolved
Hide resolved
...s/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitResolverBuilder.cs
Outdated
Show resolved
Hide resolved
...s/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitResolverBuilder.cs
Show resolved
Hide resolved
...s/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitResolverBuilder.cs
Outdated
Show resolved
Hide resolved
...s/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitResolverBuilder.cs
Outdated
Show resolved
Hide resolved
Updated IL generation logic and applied feedback. The Expression tree side will need to be changed as well, that would be run for .NET Core 2.1. |
context.Generator.Emit(OpCodes.Brfalse_S, defaultLabel); | ||
|
||
context.Generator.Emit(OpCodes.Call, CallSiteRuntimeResolverInstanceField); | ||
AddConstant(context, callSite); |
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.
This is a nice change. @pakrym but we're paying for bounds checks!! 😄
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.
We can change AddConstant to produce unsafe code with fixed
.
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.
Don't think it matters though.
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.
This method is locking and has a try finally so I'd be surprised if it mattered as well.
We can change AddConstant to produce unsafe code with fixed.
Unsafe.Add
...s/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitResolverBuilder.cs
Outdated
Show resolved
Hide resolved
Fixed the Expression Resolver Builder portion as well. Marked PR as ready for review. |
...ies/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceProviderContainerTests.cs
Show resolved
Hide resolved
...ies/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceProviderContainerTests.cs
Show resolved
Hide resolved
...ft.Extensions.DependencyInjection/src/ServiceLookup/Expressions/ExpressionResolverBuilder.cs
Outdated
Show resolved
Hide resolved
...ft.Extensions.DependencyInjection/src/ServiceLookup/Expressions/ExpressionResolverBuilder.cs
Outdated
Show resolved
Hide resolved
@maryamariyan please make sure modified tets still reproduce the original issue. |
...ies/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceProviderContainerTests.cs
Show resolved
Hide resolved
Can you please add the test from the original issue? |
@@ -1119,11 +1119,9 @@ private void ScopedServiceResolvedFromSingletonAfterCompilation2(ServiceProvider | |||
var scope = sp.CreateScope(); | |||
for (int i = 0; i < 50; i++) | |||
{ | |||
scope.ServiceProvider.GetRequiredService<A>(); | |||
Assert.Same(sp.GetRequiredService<IFakeOpenGenericService<A>>().Value, sp.GetRequiredService<A>()); |
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.
The scope is supposed to be used here no?
@pakrym the test from comment #52863 (comment) is included in the PR.
I confirmed that we get a repro with the unit tests as-is without the fix. |
src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/CallSiteTests.cs
Outdated
Show resolved
Hide resolved
@@ -11,7 +11,7 @@ namespace Microsoft.Extensions.DependencyInjection.ServiceLookup | |||
internal sealed class ServiceProviderEngineScope : IServiceScope, IServiceProvider, IAsyncDisposable, IServiceScopeFactory | |||
{ | |||
// For testing only | |||
internal Action<object> _captureDisposableCallback; | |||
internal IList<object> Disposables => _disposables ?? (IList<object>)Array.Empty<object>(); |
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.
Removes a pointer 😄. Saving the planet.
Test failure:
On UPDATE: CI is green |
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.
Let's see how this affects the performance of scoped service resolution.
Fixes: #52863
TODO: