You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core应用空闲时随机触发StackOverflowException求助

ASP.NET Core MVC 空闲时StackOverflowException 排查方案

问题概述

开发ASP.NET Core MVC应用时,遭遇随机StackOverflowException,异常仅在应用空闲时触发(非处理HTTP请求阶段)。调用栈显示是框架内部递归调用导致,但底层原因不明。曾尝试用DTO简化ViewModel,应用一度稳定运行8小时(此前10-15分钟就崩溃),但问题复现。

调用栈详情

初始触发栈:

>   System.Private.CoreLib.dll!System.ModuleHandle.ResolveMethod(System.Runtime.CompilerServices.QCallModule module, int methodToken, System.IntPtr* typeInstArgs, int typeInstCount, System.IntPtr* methodInstArgs, int methodInstCount)   
    System.Private.CoreLib.dll!System.ModuleHandle.ResolveMethodHandleInternal(System.Reflection.RuntimeModule module, int methodToken, System.IntPtr[] typeInstantiationContext, int typeInstCount, System.IntPtr[] methodInstantiationContext, int methodInstCount) Línea 1405    
    System.Private.CoreLib.dll!System.ModuleHandle.ResolveMethodHandle(int methodToken, System.RuntimeTypeHandle[] typeInstantiationContext, System.RuntimeTypeHandle[] methodInstantiationContext) Línea 1390  
    System.Private.CoreLib.dll!System.RuntimeType.GetMethodBase(System.Reflection.RuntimeModule scope, int typeMetadataToken) Línea 1743    
    System.Private.CoreLib.dll!System.Reflection.RuntimeCustomAttributeData.RuntimeCustomAttributeData(System.Reflection.RuntimeModule scope, System.Reflection.MetadataToken caCtorToken, System.Reflection.ConstArray blob) Línea 273 
    System.Private.CoreLib.dll!System.Reflection.RuntimeCustomAttributeData.GetCustomAttributes(System.Reflection.RuntimeModule module, int tkTarget) Línea 213 
    System.Private.CoreLib.dll!System.Reflection.RuntimeCustomAttributeData.GetCustomAttributesInternal(System.RuntimeType target) Línea 22 
    System.Private.CoreLib.dll!System.Reflection.CustomAttributeData.GetCustomAttributes(System.Reflection.MemberInfo target) Línea 18  
    Microsoft.Extensions.Logging.dll!Microsoft.Extensions.Logging.ProviderAliasUtilities.GetAlias(System.Type providerType) 
    Microsoft.Extensions.Logging.dll!Microsoft.Extensions.Logging.LoggerRuleSelector.Select(Microsoft.Extensions.Logging.LoggerFilterOptions options, System.Type providerType, string category, out Microsoft.Extensions.Logging.LogLevel? minLevel, out System.Func<string, string, Microsoft.Extensions.Logging.LogLevel, bool> filter)  
    Microsoft.Extensions.Logging.dll!Microsoft.Extensions.Logging.LoggerFactory.ApplyFilters(Microsoft.Extensions.Logging.LoggerInformation[] loggers)  
    Microsoft.Extensions.Logging.dll!Microsoft.Extensions.Logging.LoggerFactory.RefreshFilters(Microsoft.Extensions.Logging.LoggerFilterOptions filterOptions)  
    Microsoft.Extensions.Options.dll!Microsoft.Extensions.Options.OptionsMonitorExtensions.OnChange.AnonymousMethod__0(System.__Canon o, string _)  
    Microsoft.Extensions.Options.dll!Microsoft.Extensions.Options.OptionsMonitor<System.__Canon>.ChangeTrackerDisposable.OnChange(System.__Canon options, string name)  
    Microsoft.Extensions.Options.dll!Microsoft.Extensions.Options.OptionsMonitor<Microsoft.Extensions.Logging.LoggerFilterOptions>.InvokeChanged(string name)   
    Microsoft.Extensions.Options.dll!Microsoft.Extensions.Options.OptionsMonitor<System.__Canon>..ctor.AnonymousMethod__6_2(string name)    
    Microsoft.Extensions.Primitives.dll!Microsoft.Extensions.Primitives.ChangeToken.ChangeTokenRegistration<string>.OnChangeTokenFired()    
    Microsoft.Extensions.Primitives.dll!Microsoft.Extensions.Primitives.ChangeToken.ChangeTokenRegistration<string>.RegisterChangeTokenCallback.AnonymousMethod__7_0(object s)  
    System.Private.CoreLib.dll!System.Threading.CancellationTokenSource.Invoke(System.Delegate d, object state, System.Threading.CancellationTokenSource source) Línea 902  
    System.Private.CoreLib.dll!System.Threading.CancellationTokenSource.CallbackNode.ExecuteCallback.AnonymousMethod__9_0(object s) Línea 1139  
    System.Private.CoreLib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) Línea 183 
    System.Private.CoreLib.dll!System.Threading.CancellationTokenSource.CallbackNode.ExecuteCallback() Línea 1141   
    System.Private.CoreLib.dll!System.Threading.CancellationTokenSource.ExecuteCallbackHandlers(bool throwOnFirstException) Línea 722   
    System.Private.CoreLib.dll!System.Threading.CancellationTokenSource.NotifyCancellation(bool throwOnFirstException) Línea 639    
    System.Private.CoreLib.dll!System.Threading.CancellationTokenSource.Cancel() Línea 221  
    Microsoft.Extensions.Configuration.dll!Microsoft.Extensions.Configuration.ConfigurationManager.RaiseChanged()   
    Microsoft.Extensions.Configuration.dll!Microsoft.Extensions.Configuration.ConfigurationManager.AddSource.AnonymousMethod__1()   
    Microsoft.Extensions.Primitives.dll!Microsoft.Extensions.Primitives.ChangeToken.OnChange.AnonymousMethod__0_0(System.Action callback)   
    Microsoft.Extensions.Primitives.dll!Microsoft.Extensions.Primitives.ChangeToken.ChangeTokenRegistration<System.Action>.OnChangeTokenFired() 
    Microsoft.Extensions.Primitives.dll!Microsoft.Extensions.Primitives.ChangeToken.ChangeTokenRegistration<System.Action>.RegisterChangeTokenCallback.AnonymousMethod__7_0(object s)   
    System.Private.CoreLib.dll!System.Threading.CancellationTokenSource.Invoke(System.Delegate d, object state, System.Threading.CancellationTokenSource source) Línea 902  
    System.Private.CoreLib.dll!System.Threading.CancellationTokenSource.CallbackNode.ExecuteCallback.AnonymousMethod__9_0(object s) Línea 1139  
    System.Private.CoreLib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) Línea 183 
    System.Private.CoreLib.dll!System.Threading.CancellationTokenSource.CallbackNode.ExecuteCallback() Línea 1141   
    System.Private.CoreLib.dll!System.Threading.CancellationTokenSource.ExecuteCallbackHandlers(bool throwOnFirstException) Línea 722   
    System.Private.CoreLib.dll!System.Threading.CancellationTokenSource.NotifyCancellation(bool throwOnFirstException) Línea 639    
    System.Private.CoreLib.dll!System.Threading.CancellationTokenSource.Cancel() Línea 221  
    Microsoft.Extensions.Configuration.dll!Microsoft.Extensions.Configuration.ConfigurationProvider.OnReload()  
    Microsoft.Extensions.Configuration.FileExtensions.dll!Microsoft.Extensions.Configuration.FileConfigurationProvider.Load(bool reload)    
    Microsoft.Extensions.Configuration.FileExtensions.dll!Microsoft.Extensions.Configuration.FileConfigurationProvider..ctor.AnonymousMethod__1_1() 
    Microsoft.Extensions.Primitives.dll!Microsoft.Extensions.Primitives.ChangeToken.OnChange.AnonymousMethod__0_0(System.Action callback)   
    Microsoft.Extensions.Primitives.dll!Microsoft.Extensions.Primitives.ChangeToken.ChangeTokenRegistration<System.Action>.OnChangeTokenFired() 
    Microsoft.Extensions.Primitives.dll!Microsoft.Extensions.Primitives.ChangeToken.ChangeTokenRegistration<System.Action>.RegisterChangeTokenCallback.AnonymousMethod__7_0(object s)   
    System.Private.CoreLib.dll!System.Threading.CancellationTokenSource.Invoke(System.Delegate d, object state, System.Threading.CancellationTokenSource source) Línea 902  
    System.Private.CoreLib.dll!System.Threading.CancellationTokenSource.Register(System.Delegate callback, object stateForCallback, System.Threading.SynchronizationContext syncContext, System.Threading.ExecutionContext executionContext) Línea 610  
    System.Private.CoreLib.dll!System.Threading.CancellationToken.Register(System.Delegate callback, object state, bool useSynchronizationContext, bool useExecutionContext) Línea 290  
    System.Private.CoreLib.dll!System.Threading.CancellationToken.UnsafeRegister(System.Action<object> callback, object state) Línea 248    

重复触发栈溢出的循环调用链:

Microsoft.Extensions.Primitives.dll!Microsoft.Extensions.Primitives.CancellationChangeToken.RegisterChangeCallback(System.Action<object> callback, object state)    
    Microsoft.Extensions.Primitives.dll!Microsoft.Extensions.Primitives.ChangeToken.ChangeTokenRegistration<System.Action>.RegisterChangeTokenCallback(Microsoft.Extensions.Primitives.IChangeToken token)  
    Microsoft.Extensions.Primitives.dll!Microsoft.Extensions.Primitives.ChangeToken.ChangeTokenRegistration<System.__Canon>.OnChangeTokenFired()    
    Microsoft.Extensions.Primitives.dll!Microsoft.Extensions.Primitives.ChangeToken.ChangeTokenRegistration<System.Action>.RegisterChangeTokenCallback.AnonymousMethod__7_0(object s)   
    System.Private.CoreLib.dll!System.Threading.CancellationTokenSource.Invoke(System.Delegate d, object state, System.Threading.CancellationTokenSource source) Línea 902  
    System.Private.CoreLib.dll!System.Threading.CancellationTokenSource.Register(System.Delegate callback, object stateForCallback, System.Threading.SynchronizationContext syncContext, System.Threading.ExecutionContext executionContext) Línea 610  
    System.Private.CoreLib.dll!System.Threading.CancellationToken.Register(System.Delegate callback, object state, bool useSynchronizationContext, bool useExecutionContext) Línea 290  
    System.Private.CoreLib.dll!System.Threading.CancellationToken.UnsafeRegister(System.Action<object> callback, object state) Línea 248    

排查与修复步骤

1. 终止配置文件自动重载循环

从栈信息看,异常根源是配置重载→变更通知→日志过滤器刷新→再次触发配置变更的递归循环:

  • 先禁用配置文件自动重载,验证是否解决问题:
    // Program.cs中修改配置加载代码
    builder.Configuration.SetBasePath(Directory.GetCurrentDirectory())
                          .AddJsonFile("appsettings.json", optional: false, reloadOnChange: false)
                          .AddEnvironmentVariables();
    
  • 检查是否自定义了IConfigurationProvider,其重载逻辑是否触发了额外的配置变更事件。

2. 排查日志组件问题

栈中出现ProviderAliasUtilities.GetAlias,说明异常发生在日志过滤器刷新阶段:

  • 暂时替换为默认Console日志提供器,排除自定义日志组件的影响。
  • 检查自定义日志提供器的[ProviderAlias]属性是否存在反射加载异常,或日志过滤器逻辑是否有循环依赖。

3. 清理Options监听逻辑

OptionsMonitor.OnChange的回调可能间接触发配置/Options变更,形成循环:

  • 移除所有非必要的OptionsMonitor.OnChange注册,逐步排查哪个回调导致循环。
  • 确保Options回调中不修改配置或触发其他Options的变更事件。

4. 升级框架版本

该问题大概率是ASP.NET Core特定版本的已知Bug,升级到对应主版本的最新补丁(如.NET 6.0.25、.NET 7.0.14、.NET 8.0.0+),框架内部的递归循环问题多数已被修复。

5. 深度调试定位

  • 用Visual Studio性能探查器监控空闲时的线程栈增长,定位循环注册的回调。
  • 启用崩溃转储:在launchSettings.json中添加"environmentVariables": { "COMPlus_DbgEnableMiniDump": "1" },生成转储后用WinDbg分析递归调用链。

内容的提问来源于stack exchange,提问作者Fede

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 15:55:14