Подтвердить что ты не робот

Почему мой пул приложений IIS7 завершает работу после исключения в DLL, вызванном с страницы ASP.NET?

Я прочитал сообщения Проблема закрытия пула приложений ASP.NET и IIS 7.5: проблема с пулом приложений но они не ответили на мой вопрос.

У меня есть страница ASP.NET С#, которая в коде-образе создает экземпляр класса из DLL, поставляемого через каталог BIN, а затем вызывает метод в этом экземпляре. Метод внутри DLL выбрасывает System.ArgumentException из-за не существующего столбца в объекте DataRow. Журнал событий показывает следующую ошибку:

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). Я вручную должен перезапустить пул приложений, и сайт снова работает.

Обновление Как запрошено блок try catch из кода ASP.NET позади:

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 ); 
}

Теперь мой вопрос в том, почему относительно простое исключение, такое как System.ArgumentException, которое бросается при попытке получить доступ к не существующему столбцу DataRow, приводит к сбою всего веб-сайта? Также не помогает общий шаблон try-catch на странице ASP.NET, и это не должно стать причиной полного недопущения всего веб-сайта или неправильного предположения? Я никогда бы не подумал, что это может в основном сесть на сервер (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
}
4b9b3361

Ответ 1

Скорее всего, ваш пул приложений автоматически отключается функцией IIS Rapid Fail Protection, как вы заметили в связанных вопросах. Если вы проверите свой журнал событий, может быть несколько необработанных исключений, которые будут выполняться быстро.

Проще говоря, достаточно необработанных исключений в настраиваемом промежутке времени (по умолчанию 5 в 5 минут) отключит AppPool, вызвав ответ 503 Service Unavailable.

Обоснование этой функции заключается в том, что если у вас есть неисправное приложение, вы, вероятно, не хотите, чтобы он автоматически перезапускался при каждом последующем запросе, потребляя ресурсы и, возможно, искажая данные.

Я должен признать, что это не было поведение по умолчанию, которое я ожидал бы.

Ознакомьтесь с объяснением Рика Сталса, это немного более подробно.

Чтобы действительно исправить это, вам нужно поймать исключение или предотвратить исключение исключения (например, @leppie предлагает). Необработанные исключения должны срывать весь процесс выполнения (что означает, что один процесс запроса/рабочего процесса, а не IIS) - он делает код .Net намного легче отлаживать, поскольку он не скрывает ошибки или просто висит приложение.

Обратите внимание, что это было изменено в .Net 2.0:
http://msdn.microsoft.com/en-us/library/ms228965.aspx
http://support.microsoft.com/kb/911816

Обновление
Основываясь на вашем обновлении выше, я не думаю, что ваше исключение действительно поймано, если оно выбрано из CreateReport(). Этот метод выполняется в отдельном потоке:

exception still thrown

Вам нужен try-catch в теле CreateReport(), если его еще нет:

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

Ответ 2

Это случилось со мной однажды. Реальная ошибка (в моем случае) была переполнением стека, которое закрывало пул.

Кажется, что IIS защищал себя от потребления слишком большого количества ресурсов.

Я нашел проблему с помощью DebugDiag.

Вот где я начал: http://www.webdebug.net/index.php/2012/12/collect-iis-crash-dump-with-debugdiag/

Я хотел бы понять, почему исключение во внешней DLL может привести к отключению пула приложений IIS, даже если исключение попадает в DLL, а также при вызове метода DLL из кода, стоящего за ASP. Страница .NET.

Внешняя dll также запускается в вашем пуле приложений. Большая авария в этой DLL также приведет к сбою вашего пула приложений. Некоторые исключения не могут обрабатываться, и исключение stackoverflow является одним из них. Тема обсуждается здесь. Возможно, это то, что происходит в вашем случае.