aspnet / MicrosoftConfigurationBuilders

Microsoft.Configuration.Builders
MIT License
122 stars 61 forks source link

race condition in AzureKeyVaultConfigBuilder #189

Closed sabbadino closed 2 years ago

sabbadino commented 2 years ago

context : asp.net dotnetframework application (4.7.2) using akv config provider with default settings using Microsoft.Configuration.ConfigurationBuilders.Azure 2.0.0 and Microsoft.Configuration.ConfigurationBuilders.Base 2.0.0

We get randomly the exception below (look at the bottom) at application startup

root casue is :

at System.Linq.Enumerable.Contains (System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089) at Microsoft.Configuration.ConfigurationBuilders.AzureKeyVaultConfigBuilder+

decompiling , the offending code looks like being in private async Task GetValueAsync(string key) {

      // IT FAILS HERE
  if (vaultConfigBuilder._preload && !vaultConfigBuilder._preloadFailed && !**vaultConfigBuilder._allKeys.Contains**<string>(versionedKey.Key, (IEqualityComparer<string>) StringComparer.OrdinalIgnoreCase))

since _allKeys is null : this means that

protected override void LazyInitialize(string name, NameValueCollection config) has NOT finished to run , since _allKeys is set in that method

I cannot spot clearly the race condition clearly at present .. my suspicion is that AzureKeyVaultConfigBuilder.lazyinitialize and

public override string GetValue(string key) => Task.Run((Func<Task>) (async () => await this.GetValueAsync(key))).Result?.Value;

don't play well ..

root cause could be that AzureKeyVaultConfigBuilder.Lazyinitialize calls
base.LazyInitialize(name, config); at the begining of the code .. before _allKeys is actually set Calling base.LazyInitialize, set this._lazyInitialized = true; in the KeyValueConfigBuilder (the base class ) .. so that the AzureKeyVaultConfigBuilder is reported to be initialized before it actually is

It seems to me that , until a fix is available I have to use preload false in the AKV config provider


System.TypeInitializationException: at System.Data.Entity.Internal.AppConfig.get_DefaultInstance (EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089) at System.Data.Entity.Internal.LazyInternalConnection..ctor (EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089) at System.Data.Entity.DbContext..ctor (EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089) at WcfLinkMSCNetGlobal.Interlink_CustomerEntities..ctor (WcfCustomerGlobal, Version=2.0.0.48, Culture=neutral, PublicKeyToken=null: E:\Agents\MyMSC\Agent_04_work\2\s\WebServices\WcfCustomerGlobal\Customer.Context.cs:21) at WcfLinkMSCNetGlobal.DataRetrieval.UserGuideData.GetLanguages (WcfCustomerGlobal, Version=2.0.0.48, Culture=neutral, PublicKeyToken=null: E:\Agents\MyMSC\Agent_04_work\2\s\WebServices\WcfCustomerGlobal\DataRetrieval\UserGuideData.cs:44) at WcfLinkMSCNetGlobal.GlobalInformation.GetLanguages (WcfCustomerGlobal, Version=2.0.0.48, Culture=neutral, PublicKeyToken=null: E:\Agents\MyMSC\Agent_04_work\2\s\WebServices\WcfCustomerGlobal\GlobalInformation.svc.cs:596) at SyncInvokeGetLanguages (System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089) at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke (System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089) at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin (System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5 (System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage41 (System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4 (System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31 (System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3 (System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2 (System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11 (System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1 (System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089) at System.ServiceModel.Dispatcher.MessageRpc.Process (System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089) Inner exception System.Configuration.ConfigurationErrorsException handled at System.Data.Entity.Internal.AppConfig.get_DefaultInstance: at System.Configuration.BaseConfigurationRecord.EvaluateOne (System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a) at System.Configuration.BaseConfigurationRecord.Evaluate (System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a) at System.Configuration.BaseConfigurationRecord.GetSectionRecursive (System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a) at System.Configuration.BaseConfigurationRecord.GetSection (System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a) at System.Web.Configuration.HttpConfigurationSystem.GetApplicationSection (System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a) at System.Web.Configuration.HttpConfigurationSystem.GetSection (System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a) at System.Web.Configuration.HttpConfigurationSystem.System.Configuration.Internal.IInternalConfigSystem.GetSection (System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a) at System.Configuration.ConfigurationManager.GetSection (System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a) at System.Configuration.ConfigurationManager.get_ConnectionStrings (System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a) at System.Data.Entity.Internal.AppConfig..ctor (EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089) at System.Data.Entity.Internal.AppConfig..cctor (EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089) Inner exception System.Exception handled at System.Configuration.BaseConfigurationRecord.EvaluateOne: at Microsoft.Configuration.ConfigurationBuilders.KeyValueConfigBuilder.GetValueInternal (Microsoft.Configuration.ConfigurationBuilders.Base, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35) at Microsoft.Configuration.ConfigurationBuilders.KeyValueConfigBuilder.ProcessConfigurationSection (Microsoft.Configuration.ConfigurationBuilders.Base, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35) at System.Configuration.Internal.InternalConfigHost.System.Configuration.Internal.IInternalConfigurationBuilderHost.ProcessConfigurationSection (System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a) at System.Configuration.Internal.DelegatingConfigHost.ProcessConfigurationSection (System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a) at System.Configuration.BaseConfigurationRecord.CallHostProcessConfigurationSection (System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a) Inner exception System.AggregateException handled at Microsoft.Configuration.ConfigurationBuilders.KeyValueConfigBuilder.GetValueInternal: at System.Threading.Tasks.Task1.GetResultCore (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089) at System.Threading.Tasks.Task1.get_Result (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089) at Microsoft.Configuration.ConfigurationBuilders.AzureKeyVaultConfigBuilder.GetValue (Microsoft.Configuration.ConfigurationBuilders.Azure, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35) at Microsoft.Configuration.ConfigurationBuilders.KeyValueConfigBuilder.GetValueInternal (Microsoft.Configuration.ConfigurationBuilders.Base, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35) Inner exception System.ArgumentNullException handled at System.Threading.Tasks.Task`1.GetResultCore: at System.Linq.Enumerable.Contains (System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089) at Microsoft.Configuration.ConfigurationBuilders.AzureKeyVaultConfigBuilder+d18.MoveNext (Microsoft.Configuration.ConfigurationBuilders.Azure, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35) at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089) at Microsoft.Configuration.ConfigurationBuilders.AzureKeyVaultConfigBuilder+<>cDisplayClass13_0+<b__0>d.MoveNext (Microsoft.Configuration.ConfigurationBuilders.Azure, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)

StephenMolloy commented 2 years ago

I believe this is the race condition that is fixed by #134 and #167. Please reopen if this is still reproducible on 3.0.