-
-
Notifications
You must be signed in to change notification settings - Fork 843
Description
Describe the Bug
If I register a concrete class which inherits from an abstract generic class, a stack overflow exception occurs when an ALC child lifetime scope is disposed.
Steps to Reproduce
I've created a test console app which highlights this issue. It can be found here:
Scoped Lifetime Bug Repro(https://github.com/hemirunner426/autofaclifetime)
The test console project more closely resembles the project I discovered this issue in. The project I'm working on has a plugin arch to it and the plugins it loads can run code any time during the lifecycle of the application including bootstrap and shutdown.
I'm looking to ensure that those lifetime scopes are disposed of when the host shuts down.
To reproduce in the test console:
- Start the project.
- CTRL+C the console window to invoke IHostedService.StopAsync()
- The SOE occurs when the child scope is disposed.
NOTE: This is also reproducible if the child scope (the ALC aware lifetime scope) is disposed at any time, not just during StopAsync(). A standard child lifetime scope does not exhibit this behavior. Also, removing the generic declararion on the abstract class allows the ALC aware scope to dispose properly.
Expected Behavior
The ALC child scope disposes without an exception.
Exception with Stack Trace
System.Collections.Generic.HashSet`1<System.Reflection.Assembly>)
at Autofac.Util.Cache.TypeAssemblyReferenceProvider.PopulateAllReferencedAssemblies(System.Type, System.Collections.Generic.HashSet`1<System.Reflection.Assembly>)
at Autofac.Util.Cache.TypeAssemblyReferenceProvider.PopulateAllReferencedAssemblies(System.Type, System.Collections.Generic.HashSet`1<System.Reflection.Assembly>)
at Autofac.Util.Cache.TypeAssemblyReferenceProvider.PopulateAllReferencedAssemblies(System.Type, System.Collections.Generic.HashSet`1<System.Reflection.Assembly>)
at Autofac.Util.Cache.TypeAssemblyReferenceProvider.PopulateAllReferencedAssemblies(System.Type, System.Collections.Generic.HashSet`1<System.Reflection.Assembly>)
at Autofac.Util.Cache.TypeAssemblyReferenceProvider.PopulateAllReferencedAssemblies(System.Type, System.Collections.Generic.HaSystem.Collections.Generic.HashSet`1<System.Reflection.Assembly>)
at Autofac.Util.Cache.TypeAssemblyReferenceProvider.PopulateAllReferencedAssemblies(System.Type, System.Collections.Generic.HashSet`1<System.Reflection.Assembly>)
at Autofac.Util.Cache.TypeAssemblyReferenceProvider.PopulateAllReferencedAssemblies(System.Type, System.Collections.Generic.HashSet`1<System.Reflection.Assembly>)
at Autofac.Util.Cache.TypeAssemblyReferenceProvider.PopulateAllReferencedAssemblies(System.Type, System.Collections.Generic.HashSet`1<System.Reflection.Assembly>)
at Autofac.Util.Cache.TypeAssemblyReferenceProvider.PopulateAllReferencedAssemblies(System.Type, System.Collections.Generic.HashSet`1<System.Reflection.Assembly>)
at Autofac.Util.Cache.TypeAssemblyReferenceProvider.PopulateAllReferencedAssemblies(System.Type, System.Collections.Generic.HashSet`1<System.Reflection.Assembly>)
at Autofac.Util.Cache.TypeAssemblyReferenceProvider.PopulateAllReferencedAssemblies(System.Type, System.Collections.Generic.HashSet`1<System.Reflection.Assembly>)
at Autofac.Util.Cache.TypeAssemblyReferenceProvider.PopulateAllReferencedAssemblies(System.Type, System.Collections.Generic.HashSet`1<System.Reflection.Assembly>)
at Autofac.Util.Cache.TypeAssemblyReferenceProvider.PopulateAllReferencedAssemblies(System.Type, System.Collections.Generic.HashSet`1<System.Reflection.Assembly>)
at Autofac.Util.Cache.TypeAssemblyReferenceProvider.PopulateAllReferencedAssemblies(System.Type, System.Collections.Generic.HashSet`1<System.Reflection.Assembly>)
at Autofac.Util.Cache.TypeAssemblyReferenceProvider.PopulateAllReferencedAssemblies(System.Type, System.Collections.Generic.HashSet`1<System.Reflection.Assembly>)
at Autofac.Util.Cache.TypeAssemblyReferenceProvider.PopulateAllReferencedAssemblies(System.Type, System.Collections.Generic.HashSet`1<System.Reflection.Assembly>)
at Autofac.Util.Cache.TypeAssemblyReferenceProvider.PopulateAllReferencedAssemblies(System.Type, System.Collections.Generic.HashSet`1<System.Reflection.Assembly>)
at Autofac.Util.Cache.TypeAssemblyReferenceProvider.PopulateAllReferencedAssemblies(System.Type, System.Collections.Generic.HashSet`1<System.Reflection.Assembly>)
at Autofac.Util.Cache.TypeAssemblyReferenceProvider.PopulateAllReferencedAssemblies(System.Type, System.Collections.Generic.HashSet`1<System.Reflection.Assembly>)
at Autofac.Util.Cache.TypeAssemblyReferenceProvider.GetAllReferencedAssemblies(System.Reflection.MemberInfo, System.Collections.Generic.HashSet`1<System.Reflection.Assembly>)
at Autofac.Util.Cache.ReflectionCacheDictionary`2[[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].Clear(Autofac.Core.ReflectionCacheClearPredicate)
at Autofac.Core.ReflectionCacheSet.Clear(Autofac.Core.ReflectionCacheClearPredicate)
at Autofac.Core.Lifetime.LifetimeScope+<>c__DisplayClass23_0.<BeginLoadContextLifetimeScope>b__0(System.Object, Autofac.Core.Lifetime.LifetimeScopeEndingEventArgs)
at Autofac.Core.Lifetime.LifetimeScope+<DisposeAsync>d__46.MoveNext()
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[[Autofac.Core.Lifetime.LifetimeScope+<DisposeAsync>d__46, Autofac, Version=8.1.1.0, Culture=neutral, PublicKeyToken=17863af14b0044da]](<DisposeAsync>d__46 ByRef)
at System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder.Start[[Autofac.Core.Lifetime.LifetimeScope+<DisposeAsync>d__46, Autofac, Version=8.1.1.0, Culture=neutral, PublicKeyToken=17863af14b0044da]](<DisposeAsync>d__46 ByRef)
at Autofac.Core.Lifetime.LifetimeScope.DisposeAsync(Boolean)
at Autofac.Util.Disposable.DisposeAsync()
at AutofacLifetime.HostedService+<StopAsync>d__5.MoveNext()
at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext(System.Threading.Thread)
at System.Runtime.CompilerServices.TaskAwaiter+<>c.<OutputWaitEtwEvents>b__12_0(System.Action, System.Threading.Tasks.Task)
at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(System.Action, Boolean)
at System.Threading.Tasks.Task.RunContinuations(System.Object)
at System.Threading.Tasks.Task.TrySetResult()
at System.Threading.Tasks.Task+DelayPromise.CompleteTimedOut()
at System.Threading.TimerQueueTimer.Fire(Boolean)
at System.Threading.TimerQueue.FireNextTimers()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading.PortableThreadPool+WorkerThread.WorkerThreadStart()
Dependency Versions
Autofac: 8.1.1
.NET CORE; 8.0