ASP.NET 应用程序中的 Thread.Abort 导致 w3wp.exe 崩溃
Posted
技术标签:
【中文标题】ASP.NET 应用程序中的 Thread.Abort 导致 w3wp.exe 崩溃【英文标题】:Thread.Abort in ASP.NET app causes w3wp.exe to crash 【发布时间】:2015-11-26 21:23:30 【问题描述】:请不要在这个问题上设置重复标志 - 这不是关于“为什么会发生 ThreadAbortException”,而是关于“为什么 w3wp.exe 进程在 ThreadAbortException 之后终止”。
假设我们有一个带有以下代码示例的简单 Web 应用程序:
protected void Page_Load(object sender, EventArgs e)
Response.Redirect("http://google.com");
这实际上意味着类似(参见Is Response.End() considered harmful?):
protected void Page_Load(object sender, EventArgs e)
...response write some data...
System.Threading.Thread.CurrentThread.Abort();
在我的机器(Windows 10 Pro + IIS)上,此代码导致 IIS 池进程终止,错误代码为 0x0(重定向未执行)。在其他机器(不是 Windows 10)上,此代码仅生成 ThreadAborted 异常,但进程继续工作(重定向执行)。
有人可以检查这个示例并解释发生了什么吗?
更新 这里有一些与此问题相关的 Windows 事件日志。
日志 #1
发生未处理的异常,进程终止。
应用程序 ID:/LM/W3SVC/1/ROOT/AS
进程 ID:6700
异常:System.Threading.ThreadAbortException
消息:线程被中止。
堆栈跟踪:在 System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest WR,HttpContext 上下文)在 System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 标志)在 System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 标志)
日志 #2
Faulting application name: w3wp.exe, version: 10.0.10240.16384, time stamp: 0x559f3dad
Faulting module name: KERNELBASE.dll, version: 10.0.10240.16384, time stamp: 0x559f3b2a
Exception code: 0xe0434352
Fault offset: 0x000b3e28
Faulting process id: 0x1a2c
Faulting application start time: 0x01d0e4b1b3ed01cb
Faulting application path: C:\WINDOWS\SysWOW64\inetsrv\w3wp.exe
Faulting module path: C:\WINDOWS\SYSTEM32\KERNELBASE.dll
Report Id: 23b5298d-3b36-49c7-a294-de9c864b703f
Faulting package full name:
Faulting package-relative application ID:
【问题讨论】:
@Nanhydrin,Thread.Abort 只是一个示例,用于显示 Response.Redirect 内部发生的情况,即 Response.Redirect() 调用 Response.End() 然后调用 Thread.Abort() (见***.com/questions/1087777/…) 我也看到了这个问题,特别是在安装 .Net 4.6 之后(不,我还不知道为什么)。即使我的项目没有针对 4.6,这也是将使用的框架,如以下链接所示:developers.slashdot.org/story/15/07/28/160255/… 我遇到了完全相同的问题,但我的同事可以毫无问题地运行完全相同的代码。 @StingyJack 不,这不是重复的。另一个问题是关于为什么 Response.End 会导致 ThreadAbortException,这个问题是关于为什么 ThreadAbortException 会导致 w3wp 失败并出现 Win32Exception 您是否为优化错误安装了 RyuJIT 更新 KB,或者之前有任何解决方法来避免它?本文 cmets 在使用解决方法时提到了相同类型的活动。 blogs.msdn.com/b/dotnet/archive/2015/07/28/… 【参考方案1】:我能够在安装了 .NET 4.6 的 Server 2008r2 上重现该问题。
我怀疑你们其他人也遇到了同样的问题; ThreadAbortExceptions 在事件日志中杀死应用程序池(尽管在我的情况下,any 未处理的异常会导致问题;但这可能只是一个全局异常处理程序捕获它并以 Response.End 或 Redirect 结束) .转储堆栈跟踪也与 Ian 的答案中的那个匹配。
为该问题打开了一个 MS Connect 票证,最近的 KB 修补程序为我解决了该问题。
连接文章:https://connect.microsoft.com/VisualStudio/feedback/details/1605438/disabling-ryujit-breaks-asp-net
知识库修补程序: https://support.microsoft.com/en-us/kb/3098786
【讨论】:
【参考方案2】:到目前为止,我只有一个解决方案:
static class WebExtensions
public static void EndSafe(this HttpResponse response)
response.Flush();
response.SuppressContent = true;
HttpContext.Current.ApplicationInstance.CompleteRequest();
public static void RedirectSafe(this HttpResponse response, string url)
response.Redirect(url, false);
HttpContext.Current.ApplicationInstance.CompleteRequest();
然而,这迫使我确保在它之后不会执行任何代码:
...some code
response.RedirectSafe(url);
return; //<-- important
...some more code
请注意,在某些情况下(例如递归调用)仅“return”是不够的,在某些情况下您可能需要避免使用“return”(使用 try-finally 结构)
【讨论】:
我认为这只是掩盖了问题,并且您质疑为什么 ThreadAbortException 一直崩溃到 w3wp.exe 是正确的。升级到 .NET 4.6 后,我目前正在诊断类似的问题。 升级到 IIS 8 和 .NET 4.6 后遇到了同样的问题。在 Application_BeginRequest 内部调用 Response.Redirect() 会使整个进程崩溃。这段代码修复了它。在 IIS 7 上,这对我们来说不是问题。【参考方案3】:在重新启动以安装 Windows 更新后,我今天在 Windows 8.1 上遇到了同样的问题。
问题是我在注册表中手动禁用了 RyuJIT,due to this issue,通过添加 useLegacyJit
DWORD 并将其设置为 1(请参阅 Method #3)。但是其中一个更新在同一位置创建了 UseRyuJIT
键并将其设置为 1,这显然使 ASP.NET 非常混乱。
解决方案是将useLegacyJit
设置为0 并发出iisreset
。在那之后,世界上一切都很好。
当我调试w3wp.exe
转储时,WinDbg 的!clrstack
显示以下帧。也许这会帮助其他正在谷歌搜索解决方案的同样错误的人:
000000ef9892be98 00007ffa0e2d1fea [HelperMethodFrame: 000000ef9892be98]
000000ef9892bf80 00007ff99d776588 System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr, IntPtr, IntPtr, Int32)
000000ef9892df90 00007ff9fc172345 [FaultingExceptionFrame: 000000ef9892df90]
000000ef9892e490 00007ff99d7796c0 System.Web.HttpRuntime.ProcessRequestNotificationPrivate(System.Web.Hosting.IIS7WorkerRequest, System.Web.HttpContext)
000000ef9892e520 00007ff99d777377 System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr, IntPtr, IntPtr, Int32)
000000ef9892e700 00007ff99d77655a System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr, IntPtr, IntPtr, Int32)
000000ef9892e740 00007ff99d775c11 DomainNeutralILStubClass.IL_STUB_ReversePInvoke(Int64, Int64, Int64, Int32)
000000ef9892ef58 00007ff9fc100b4e [InlinedCallFrame: 000000ef9892ef58] System.Web.Hosting.UnsafeIISMethods.MgdIndicateCompletion(IntPtr, System.Web.RequestNotificationStatus ByRef)
000000ef9892ef58 00007ff99d78cc1b [InlinedCallFrame: 000000ef9892ef58] System.Web.Hosting.UnsafeIISMethods.MgdIndicateCompletion(IntPtr, System.Web.RequestNotificationStatus ByRef)
000000ef9892ef30 00007ff99d78cc1b DomainNeutralILStubClass.IL_STUB_PInvoke
000000ef9892f000 00007ff99d77756c System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr, IntPtr, IntPtr, Int32)
000000ef9892f1e0 00007ff99d77655a System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr, IntPtr, IntPtr, Int32)
000000ef9892f220 00007ff99d775c11 DomainNeutralILStubClass.IL_STUB_ReversePInvoke(Int64, Int64, Int64, Int32)
000000ef9892f418 00007ff9fc100da3 [ContextTransitionFrame: 000000ef9892f418]
【讨论】:
感谢堆栈跟踪;这就是让我来到这里的原因,并确认其他人也遇到了同样的问题,而我并没有发疯。 @MisterZimbu 很高兴我能帮上忙!【参考方案4】:我在 Win7 SP1 上遇到了同样的问题。 Web 应用程序针对 .net 4.5.2 编译并在 .net 4.6 上运行。而且我没有弄乱 useLegacyJit 或 useRyuJIT 注册表标志。
原来“启用 32 位应用程序”在我的应用程序域上不必要地设置为已启用。禁用它可以解决问题。
【讨论】:
以上是关于ASP.NET 应用程序中的 Thread.Abort 导致 w3wp.exe 崩溃的主要内容,如果未能解决你的问题,请参考以下文章
将 asp.net WebForms 应用程序中的组合表单/Windows 身份验证迁移到 asp.net MVC 应用程序