Переполнение стека в .NET отправляет IIS на 100% загрузку процессора - почему нет StackOverflowException? - PullRequest
15 голосов
/ 10 мая 2011

У меня был некоторый код в приложении 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?

Ответы [ 3 ]

5 голосов
/ 10 мая 2011

Возможно, JIT-компилятор оптимизировал вызов метода к YourClass::get_Comments() (как это будет выглядеть в IL) и встроил код в конструкцию цикла jmp (или каким бы то ни было ассемблером x86), потому что там не былоНикаких ценностей не передается.Просто мысль.

Эту старую статью стоит посмотреть:

Оптимизация Jit: Inlining (II)

"Типичный примердействительно хорошим кандидатом для встраивания является метод получения / установки свойств. Обычно это действительно очень маленькие методы, которые обычно просто извлекают или сохраняют память, поэтому обычно их размер и скорость выигрывают. "

Как есть:

Написание высокопроизводительных управляемых приложений: учебник для начинающих - код и CLR JIT

Я также воспроизвел этопростое консольное приложение:

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 и компиляции сборки релиза приложение работает вечно.Это говорит о том, что, вероятно, произошло встраивание в цикл.

Это также относится к C # 2.0, 3.0 и 4.0.

1 голос
/ 10 мая 2011

Я попытался поместить этот код в библиотеку классов и запустить его с модульным тестом.

Это приводит к сбою агента тестирования MS с исключением переполнения стека.вы получаете исключение переполнения стека.Это сбой пула приложений.Затем IIS извлекает новую копию пула приложений, и он снова выходит из строя ....

Проверьте ведение журнала событий на предмет повторного использования / остановки пула приложений.

0 голосов
/ 10 мая 2011

Это происходит как в разработке, так и в выпуске?

Извините, я точно не знаю, но вот мои предположения. Где-то у вас настроен автоповтор. Таким образом, процесс операции завершается с ошибкой StackOverflowException. Вместо того, чтобы пользователь получал сообщение, IIS повторяет попытку с новым процессом. Это продолжается и продолжается и продолжается. И поэтому повторные попытки съедают весь процессор.

Я искал, чтобы попытаться найти механизм автоповтора, который мог бы объяснить его, но пока не повезло, но вы узнаете больше о своей конфигурации.

Еще одна проверка, которую вы можете попробовать - написать что-то, что выделяет огромный объем памяти, и посмотреть, происходит ли то же самое с OutOfMemoryException. Если это так, то это почти наверняка автоповтор.

...