Переполнение стека в .NET отправляет IIS на 100% использование ЦП - почему нет StackOverflowException?
У меня был код в приложении ASP.NET, запущенном на сервере Server 2008 R2 + IIS 7.5. Всякий раз, когда я загружал определенную страницу, она зависала навсегда и отправляла IIS на 100% использование ЦП. В конечном итоге я обнаружил проблему.
public string Comments
{
get { return this.Comments; }
}
Упс - должно быть return this.Photo.Comments
. Итак, мой вопрос: почему .NET не генерировал исключение StackOverflowException, но вместо этого IIS запускался на 100% -ном процессоре намного дольше, чем следовало бы. По моему опыту программирования с .NET требуется несколько секунд или меньше, чтобы получить исключение StackOverflowException при выполнении чего-то подобного выше. Итак, как он мог работать в течение почти 30 минут на IIS?
Ответы
Ответ 1
Возможно, компилятор JIT оптимизировал вызов метода на YourClass::get_Comments()
(каким будет выглядеть ИЛ) и нарисует код с помощью конструкции цикла jmp
(или любого другого, что было бы x64-ассемблером), потому что там любые передаваемые значения. Просто мысль.
Эта старая статья стоит посмотреть:
Jit Optimizations: Inlining (II)
"Типичный пример действительно хорошего кандидат на вложение - это собственность геттер/сеттер. Обычно это действительно небольшие методы, которые обычно просто сделать выборку памяти или сохранить ее, так что это обычно размер и скорость выигрывают для встроенных их".
Как есть:
Написание высокопроизводительных управляемых приложений: управляемый праймер код и JIT CLR
Я также воспроизвел это с помощью простого консольного приложения:
class Program
{
static void Main(string[] args)
{
MyClass mc = new MyClass();
string s = mc.Comments;
}
}
public class MyClass
{
public string Comments
{
get { return this.Comments; }
}
}
В режиме отладки с отключенными оптимизациями я получаю исключение. После включения Jit Optimisations и компиляции сборки релиза приложение запускается вечно. Это говорит о том, что, вероятно, произошло вложение в цикл.
Это также относится к С# 2.0, 3.0 и 4.0.
Ответ 2
Я попытался поместить этот код в библиотеку классов и запустить его с помощью unit test.
Сбой агента проверки MS с исключением.
Что может случиться, так это то, что вы получаете исключение stackoverflow. Это приводит к сбою пула приложений. Затем IIS вытаскивает новую копию пула приложений, и он снова разбивается...
Проверьте регистрацию событий для повторного использования/остановки пула приложений.
Ответ 3
Это происходит в разработке, а также в выпуске?
Мне жаль, что я не знаю точно, но вот мои предположения. Где-то у вас есть автоматическая повторная попытка. Таким образом, процесс операции выходит из строя из исключения StackOverflowException. Вместо того, чтобы пользователь получал сообщение, IIS повторяет новый процесс. Это продолжается и продолжается. И поэтому повторяющиеся повторы едят весь процессор.
Я искал, чтобы попытаться найти механизм автозагрузки, который мог бы его учитывать, но пока не повезло, но вы узнаете больше о своей конфигурации.
Еще одна проверка, которую вы могли бы попробовать, это написать что-то, что выделяет огромный объем памяти и посмотреть, происходит ли то же самое с OutOfMemoryException. Если это так, это почти наверняка авто-повтор.