Stack overflow in .NET sends IIS to 100% CPU usage - why no StackOverflowException?
I had some code in an ASP.NET application running on Server 2008 R2 + IIS 7.5. Whenever I loaded a particular page, it would hang forever and send IIS to 100% CPU usage. I eventually tracked down the problem.
public string Comments
{
get { return this.Comments; }
}
Oops - should have been return this.Photo.Comments
. So, my question is, why didn't .NET generate a StackOver开发者_运维百科flowException, but instead let IIS run at 100% CPU for far longer than it should have taken. In my experience programming with .NET, it takes seconds or less to get a StackOverflowException when doing something like the above. So how could it still be running for almost 30 minutes on IIS?
It's possible the JIT compiler optimised out a method call to YourClass::get_Comments()
(which is what the IL would look like) and inlined the code with a jmp
(or whatever the x86 assembler would be) loop construct because there weren't any values being passed around. Just a thought.
This old article is worth a look:
Jit Optimizations: Inlining (II)
"A typical example of a really good candidate for inlining is a property getter/setter. These are usually really small methods that usually just do a memory fetch or store, so it's usually a size and speed win to inline them."
As is:
Writing High-Performance Managed Applications : A Primer - Managed Code and the CLR JIT
I also reproduced this with a simple console application:
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; }
}
}
In debug mode with optimisations turned off I get a stack overflow exception thrown. Upon turning on Jit Optimisations and compiling a release build the app just runs forever. This suggests that inlining to a loop has probably happened.
This also appears to be the case with C#2.0, 3.0 and 4.0.
I tried putting this code into a class library and running it with a unit test.
It crashes the MS test agent with a stack overflow exception.
What may be happening is that you are getting a stackoverflow exception. This is crashing the application pool. IIS then pulls up a new copy of the app pool, and it gets crashed again ....
Check your event logging for application pool recycling / stops.
Does this happen in development as well as release?
I'm sorry I don't know for sure, but here is my speculation. Somewhere you have an Auto-retry configured. So the operation process fails from a StackOverflowException. Rather than the user getting a message, IIS retries with a new process. This goes on and on and on. And so the repeated retries eat all the CPU.
I've searched to try and find an auto-retry mechanism that might account for it, but had no luck so far, but you will know more about your configuration.
Another check you could try is write something which allocates a huge amount of memory and see if the same thing happens with OutOfMemoryException. If it does, it is almost certainly an auto-retry.
精彩评论