-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Description
Description
v7 has introduced a change in behaviour when the first creation of an IOptionMonitor<T> instance is done many times concurrently.
Given configuration code like this:
services.AddOptions<TestOptions>("testing")
.Configure<DummyService>((options, dummyService) =>
{
Console.WriteLine("Configuring TestOptions instance");
});
In dotnet 6 you could create multiple instances of IOptionsMonitor<TestOptions> concurrently on startup and the configuration callback would only be called once.
In dotnet 7, the same operation results in multiple calls to the configuration callback.
This was originally noticed as configuration of Microsoft.Identity.Web authentication stopped working correctly post upgrade to dotnet 7.
I raised a ticket there (AzureAD/microsoft-identity-web#1995), but it was then narrowed down to be a Microsoft.Extensions.Options problem instead, so raising ticket here as @Tratcher suggested.
Reproduction Steps
https://github.com/petedishman/OptionsTest contains a reproduction of this problem with two identical projects, except one is configured with the v6 versions of the libraries, and the other with v7.
The code sets up configuration as above, and then creates (concurrently) multiple instances of a service that take IOptionsMonitor<TestOptions> as a dependency.
When run against v6 libraries you get this output:
C:\build\examples\OptionsTest\OptionsTest6> dotnet run
Building...
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
Content root path: C:\build\examples\OptionsTest\OptionsTest6
Creating TestOptions instance
Creating TestOptions instance
Creating TestOptions instance
Creating TestOptions instance
Creating TestOptions instance
Configuring TestOptions instance
When run against v7, you get this:
C:\build\examples\OptionsTest\OptionsTest7> dotnet run
Building...
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
Content root path: C:\build\examples\OptionsTest\OptionsTest7
Creating TestOptions instance
Creating TestOptions instance
Creating TestOptions instance
Creating TestOptions instance
Creating TestOptions instance
Configuring TestOptions instance
Configuring TestOptions instance
Configuring TestOptions instance
Configuring TestOptions instance
Configuring TestOptions instance
After the initial concurrent access, subsequent calls to inject an IOptionsMonitor<TestOptions> instance correctly don't re-run the configuration callback.
Expected behavior
The configuration callback should only be executed when multiple instances are requested concurrently
Actual behavior
The configuration callback is called multiple times when initialised many times concurrently
Regression?
Yes - regression since v6
#66688 seems likely to be related/the cause
Known Workarounds
Initialising the IOptionsMonitor<T> instance once manually before any possible concurrent access works around the problem.
Configuration
Tested on .net 6 & 7 running on both windows & linux x64. Does not appear to be platform specific.
Other information
No response