损坏状态异常--StackOverflowException导致服务挂掉
最近遇到一个问题,服务发版后,过几分钟就会挂掉,按照我以往的经验分析可能是CPU达到100%或内存不足,但是我查看了服务的状态,CPU和内存都还很充裕。此时我晕了…,通过分析dump文件,才知道是因为StackOverflowException导致服务挂掉了。
那问题来了:
1:是什么导致了StackOverflowException。
2:为什么StackOverflowException导致服务挂掉了。
一.问题1:是什么导致了StackOverflowException
看代码,如下图所示:
1:通过pIds的个数控制循环次数
2:循环回调本函数
3:出现StackOverflowException是因为代码漏洞,虽然在循环调用函数,但是pIds并没有增加,因此没有阻止死循环,导致堆栈持续增加,直到堆栈溢出。
二.问题2:为什么StackOverflowException导致服务挂掉
1:原因是CLR认为本机代码抛出的一些异常是损坏状态异常(corrupted state exeption,CSE),因为它们一般是由CLR自身的bug造成,或者由托管开发人员无法控制的本机代码的bug造成。CLR默认不让托管代码捕捉这些异常,而将自己挂掉。
2:损坏状态异常包括如下几种:
- EXCETION_ACCESS_VIOLATION
- EXCETION_STACK_OVERFLOW
- EXCETION_ILLEGAL_INSTRUCTION
- EXCETION_IN_PAGE_ERROR
- EXCETION_INVALID_DISPOSITION
- EXCETION_NONCONTINUABLE_ EXCETION
- EXCETION_PRIV_ INSTRUCTION
- EXCETION_UNWIND_CONSOLIDATE
因为StackOverflowException属于损坏状态异常,所以它会导致服务挂掉。
3:CLR不处理损坏状态异常的原因如下:
- 这种异常返回给客户端,客户端对这种信息基本上是束手无策
- 服务器应尽量少暴露自己的相关信息,防止自己被“黑”的几率
三.排查问题
1:排查问题分为如下几步:
- 出现异常是抓取dump文件。
- 分析dump文件
- 分析源代码
2:此处会具体介绍分析dump文件的过程。
-
用!analyze –v分析,可以看到是Stack overflow异常
-
用!clrstack 分析堆栈,发现是IfDimensionCircular在循环调用自己
3:分析源代码
找到代码IfDimensionCircular,分析存在循坏调用的原因,这就是本文刚开始说的那段代码,这里就不再重复分析了.
四.结论
1:并不是所有的异常CLR都会处理的.
2:不被处理的异常会导致程序挂掉.