優化拍攝模式我有一個HttpHandler的,看起來像這樣:C#HttpHandler的崩潰IIS - 但只有在與
public class GoodIISHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
try
{
try
{
context.Response.End();
}
catch (Exception)
{
}
}
finally
{
Console.WriteLine("Inside finally block");
}
}
public bool IsReusable => true;
}
它的偉大工程!除了在發佈模式下編譯並啓用了優化並隨後執行(在運行帶有.NET 4.5.2的IIS 8的Windows Server 2012上)之外。然後它崩潰IIS。
發生未處理的異常,並且進程終止。
應用程序ID:/ LM/W3SVC/1592535739/ROOT/HttpHandlerApp
進程ID:648
例外: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標誌)
和
錯誤的應用程序名:w3wp.exe,版本:8.0.9200.16384,時間戳:0x50108835
錯誤模塊名稱:KERNELBASE.dll,版本:6.2.9200.17366,時間戳:0x554d4531
異常代碼:0xe0434352
故障偏移:0x000000000004aea8
出錯進程ID:0x288
錯誤的應用程序的開始時間:0x01d1ec2c7db735a6
錯誤的應用程序路徑:C:\ Windows \ System32下\ INETSRV \ w3wp.exe的
錯誤模塊路徑:C:\ Windows \ System32下\ KERNELBASE.dll
報告編號:bb7471fa-581f-11e6-93f1-00155d461b1c
斷裂作用包全名:
斷裂作用包相對應用程序ID:
我已經縮小了問題的範圍,即在啓用/禁用優化時更改的IL的特定位。
這裏是IL爲ProcessRequest
不崩潰IIS:
.method public hidebysig newslot virtual final
instance void ProcessRequest(class [System.Web]System.Web.HttpContext context) cil managed
{
// Code size 30 (0x1e)
.maxstack 1
.try
{
.try
{
IL_0000: ldarg.1
IL_0001: callvirt instance class [System.Web]System.Web.HttpResponse [System.Web]System.Web.HttpContext::get_Response()
IL_0006: callvirt instance void [System.Web]System.Web.HttpResponse::End()
IL_000b: leave.s IL_0010
} // end .try
catch [mscorlib]System.Exception
{
IL_000d: pop
IL_000e: leave.s IL_0010
} // end handler
IL_0010: leave.s IL_001d
} // end .try
finally
{
IL_0012: ldstr "Inside finally block"
IL_0017: call void [mscorlib]System.Console::WriteLine(string)
IL_001c: endfinally
} // end handler
IL_001d: ret
} // end of method GoodIISHandler::ProcessRequest
爲了使IIS崩潰,變更線19
IL_000e: leave.s IL_001d
這種變化直接使嵌套catch塊退出到方法返回指令,而不訪問try..finally的try塊中剩餘的單個指令。
我的假設是,崩潰與ThreadAbortException
(其中一個context.Response.End()
將拋出)的魔術自動重投行爲有關,以及CLR和/或IIS和/或ASP.NET如何管理該行爲;所以當優化的IL從catch塊直接退出到返回指令時,在IL_0010
處插入的CLR/IIS/ASP.NET錯過了一些假想的中止重置魔術,並且ThreadAbortException取消了整個IIS。
還有散落在互聯網這個行爲(例如these msdn docs狀態ThreadAbortException is a special exception that can be caught, but it will automatically be raised again at the end of the catch block.
和this blog提到... notably ASP.NET, even aborts individual threads routinely without unloading the domain. They backstop the ThreadAbortExceptions, call ResetAbort on the thread and reuse it or return it to the CLR ThreadPool.
)線索,但我無法找到任何具體的有關機制。
所以我想我的問題是:這是怎麼回事?我是否真的發現CLR或IIS或ASP.NET錯誤與這種線程中止機制被IL優化擊敗?
對於任何感興趣的人,可以在https://github.com/jamezor/HttpHandlerRepro找到完全腳本的repro。
您使用的是哪個版本的.NET Framework? 4.6.0已知有一些問題,您應該禁用RyuJIT來解決一些問題。 –
我們正在使用.NET 4.5.2運行,所以不能責怪4.6不幸的是:) – Jamezor