为什么从ASP.NET页调用的DLL中出现异常后,我的IIS7应用程序池会关闭? [英] Why does my IIS7 application pool shutdown after an exception in a DLL called from an ASP.NET page?

查看:162
本文介绍了为什么从ASP.NET页调用的DLL中出现异常后,我的IIS7应用程序池会关闭?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已阅读帖子 ASP.NET应用程序池关闭问题 IIS 7.5:应用程序池问题,但他们没有回答我的问题.

我有一个C#ASP.NET页面,该页面在代码隐藏中从通过BIN目录提供的DLL中实例化一个类,然后在此实例上调用一个方法.由于DataRow对象中不存在的列,DLL中的方法将抛出System.ArgumentException.事件日志显示以下错误:

Source: ASP.NET 2.0.50727.0
Application ID: /LM/W3SVC/1/ROOT/...
Process ID: 9476
Exception: System.ArgumentException
Message: Column 'someColumn' does not belong to table.
StrackTrace: 

ASP.NET页中的调用代码将方法调用包装在通用try-catch块中.当我请求该页面时,这会使我的IIS实例的相应应用程序池崩溃,并且我的网站不再可用(错误503).我必须手动重新启动应用程序池,然后站点才能再次工作.

更新 根据要求,从ASP.NET代码后面的try catch块:

try
{
    SomeExternalClass someExternalClass = new SomeExternalClass();
    someExternalClass.SomeMethod( someId );
}
catch( Exception ex )
{
    // "smp" is an instance of "StatusMessagePanel", a control we use on all pages 
    // to show error information, basically a div container with an icon.
    smp.ShowError( ex.Message ); 
}

现在我的问题是,为什么在尝试访问不存在的DataRow列时抛出诸如"c0>"之类的相对简单"的异常会使整个网站崩溃? ASP.NET页的通用try-catch块既无济于事,也不应该是完全使整个网站不可用的原因,或者这是错误的假设吗?我从没想过这基本上可以使(II)服务器瘫痪.

预期人们会告诉我在访问列之前应先检查列是否存在:我知道这一点,并且旧代码已更改,但这不是我如上所述的问题,我想知道后果为何如此严重.

更新2

在DLL内部调用有问题的方法会启动包裹在try-catch块中的线程:

[...]
try
{
    ThreadStart starter = () => CreateReport(...)
    Thread thread = new Thread( starter );
    thread.Start();
    if( !thread.Join( TimeSpan.FromMinutes( 15 ) ) )
    {
        // Log some timeout warning
    }
    else
    {
        // Log information about successful report generation
    }
}
catch( Exception ex )
{
    // Log error information
}

解决方案

很可能您的应用程序池已被

查看里克·斯塔尔(Rick Stahls)的解释,它的深度要深一些.

要真正解决此问题,您需要捕获异常,或防止引发异常(如@leppie建议).未处理的异常应该会破坏整个执行过程(意味着单个请求/工作进程,而不是IIS)-它使.Net代码更易于调试,因为它不会隐藏错误或只是挂起了应用程序. >

请注意,这在.Net 2.0中已更改:
http://msdn.microsoft.com/en-us/library/ms228965.aspx
http://support.microsoft.com/kb/911816

更新
根据上面的更新,如果从CreateReport()引发异常,我认为您实际上并未捕获到该异常.该方法在单独的线程上执行:

如果还没有,请在CreateReport()正文中进行try-catch:

public static void CreateReport() {
    try {
        throw new Exception("reducto");
    } catch {
        Console.WriteLine("done did.");
    }
}

I've read the posts ASP.NET application pool shutdown problem and IIS 7.5: problem with Application pool but they didn't answer my question.

I've got a C# ASP.NET page that in code-behind instantiates a class from a DLL supplied via the BIN directory, then calls a method on this instance. The method inside the DLL throws System.ArgumentException due to a non existing column in a DataRow object. The event log shows the following error:

Source: ASP.NET 2.0.50727.0
Application ID: /LM/W3SVC/1/ROOT/...
Process ID: 9476
Exception: System.ArgumentException
Message: Column 'someColumn' does not belong to table.
StrackTrace: 

The calling code in the ASP.NET page wraps the method call in a generic try-catch block. When I request the page, this crashes the corresponding application pool of my IIS instance and my web site is no longer available (Error 503). I manually have to restart the application pool and the site works again.

Update As requested the try catch block from the ASP.NET code behind:

try
{
    SomeExternalClass someExternalClass = new SomeExternalClass();
    someExternalClass.SomeMethod( someId );
}
catch( Exception ex )
{
    // "smp" is an instance of "StatusMessagePanel", a control we use on all pages 
    // to show error information, basically a div container with an icon.
    smp.ShowError( ex.Message ); 
}

Now my question is why a relatively "simple" exception such as the System.ArgumentException being thrown when trying to access a non existing DataRow column, crashes the whole website? Neither does the generic try-catch block of the ASP.NET page help, nor should this be the reason to completely make the whole website unavailable, or is that a wrong assumption? I'd never have thought that this can basically take the (II)server down.

In anticipation of people telling me that I should check for column existence before I access them: I know about that and the legacy code has now been changed, but this isn't my question as described above, I'd like to know why the consequences are so drastic.

Update 2

The method in question being called inside the DLL starts a thread that is wrapped in a try-catch block:

[...]
try
{
    ThreadStart starter = () => CreateReport(...)
    Thread thread = new Thread( starter );
    thread.Start();
    if( !thread.Join( TimeSpan.FromMinutes( 15 ) ) )
    {
        // Log some timeout warning
    }
    else
    {
        // Log information about successful report generation
    }
}
catch( Exception ex )
{
    // Log error information
}

解决方案

Most likely your application pool is being shut down automatically by IIS's Rapid Fail Protection feature, as you note in the linked questions. If you check your event log, there may be multiple unhandled exceptions being thrown in rapid succession.

Simply put, enough unhandled exceptions in a configurable timespan (the default is 5 in 5 minutes) will shut down the AppPool, causing the 503 Service Unavailable response.

The reasoning behind this feature is that if you have a faulty application, you probably don't want it to be automatically restarted on every subsequent request, consuming resources and possibly corrupting data.

I have to admit that this isn't the "default" behavior I would have expected either.

Check out Rick Stahls explanation, it's a bit more in depth.

To really fix this, you need to catch the exception, or prevent the exception from being thrown (like @leppie suggests). Unhandled exceptions are supposed to tear down the entire executing process (meaning that single request/worker process, not IIS) - it makes .Net code much easier to debug, because it doesn't hide the errors or simply hang the application.

Note that this was changed in .Net 2.0:
http://msdn.microsoft.com/en-us/library/ms228965.aspx
http://support.microsoft.com/kb/911816

Update
Based on your update above, I don't think your exception is actually caught, if it is thrown from CreateReport(). That method is executing on a separate thread:

You need a try-catch in the body of CreateReport() if there isn't one already:

public static void CreateReport() {
    try {
        throw new Exception("reducto");
    } catch {
        Console.WriteLine("done did.");
    }
}

这篇关于为什么从ASP.NET页调用的DLL中出现异常后,我的IIS7应用程序池会关闭?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆