损坏状态异常--*Exception导致服务挂掉

最近遇到一个问题,服务发版后,过几分钟就会挂掉,按照我以往的经验分析可能是CPU达到100%或内存不足,但是我查看了服务的状态,CPU和内存都还很充裕。此时我晕了…,通过分析dump文件,才知道是因为*Exception导致服务挂掉了。
那问题来了:
1:是什么导致了*Exception。
2:为什么*Exception导致服务挂掉了。

一.问题1:是什么导致了*Exception

看代码,如下图所示:
1:通过pIds的个数控制循环次数
2:循环回调本函数
3:出现*Exception是因为代码漏洞,虽然在循环调用函数,但是pIds并没有增加,因此没有阻止死循环,导致堆栈持续增加,直到堆栈溢出。
损坏状态异常--*Exception导致服务挂掉

二.问题2:为什么*Exception导致服务挂掉

1:原因是CLR认为本机代码抛出的一些异常是损坏状态异常(corrupted state exeption,CSE),因为它们一般是由CLR自身的bug造成,或者由托管开发人员无法控制的本机代码的bug造成。CLR默认不让托管代码捕捉这些异常,而将自己挂掉。

2:损坏状态异常包括如下几种:

  1. EXCETION_ACCESS_VIOLATION
  2. EXCETION_STACK_OVERFLOW
  3. EXCETION_ILLEGAL_INSTRUCTION
  4. EXCETION_IN_PAGE_ERROR
  5. EXCETION_INVALID_DISPOSITION
  6. EXCETION_NONCONTINUABLE_ EXCETION
  7. EXCETION_PRIV_ INSTRUCTION
  8. EXCETION_UNWIND_CONSOLIDATE

因为*Exception属于损坏状态异常,所以它会导致服务挂掉。

3:CLR不处理损坏状态异常的原因如下:

  1. 这种异常返回给客户端,客户端对这种信息基本上是束手无策
  2. 服务器应尽量少暴露自己的相关信息,防止自己被“黑”的几率

三.排查问题

1:排查问题分为如下几步:

  1. 出现异常是抓取dump文件。
  2. 分析dump文件
  3. 分析源代码

2:此处会具体介绍分析dump文件的过程。

  1. 用!analyze –v分析,可以看到是Stack overflow异常
    损坏状态异常--*Exception导致服务挂掉

  2. 用!clrstack 分析堆栈,发现是IfDimensionCircular在循环调用自己

损坏状态异常--*Exception导致服务挂掉
3:分析源代码
找到代码IfDimensionCircular,分析存在循坏调用的原因,这就是本文刚开始说的那段代码,这里就不再重复分析了.

四.结论

1:并不是所有的异常CLR都会处理的.
2:不被处理的异常会导致程序挂掉.