Chinaunix首页 | 论坛 | 博客
  • 博客访问: 573762
  • 博文数量: 493
  • 博客积分: 2891
  • 博客等级: 少校
  • 技术积分: 4960
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-17 17:11
文章分类

全部博文(493)

文章存档

2010年(493)

分类:

2010-05-12 17:12:34

2 关键过程、根本原因分析
首先打印运行信息,发现为发送notification的函数,经过对此函数进行仔细的检查修改后发现,死机问题还是存在。有时候还是在发送Notification的位置,但也有其他的位置。现象比较奇怪,通过调试运行,问题又很少出现,通过分析问题现象应该是内存越界引起的,因为一个地方越界后,下一次访问(申请、释放)内存的时候必然死掉。
下面首先进行逻辑分析,首先网管Agent启动,当系统启动后开始加载全部的数据,而此时Agent不会马上死掉,说明不是数据加载因起,此时同样有Notification, 说明Notification业务不是必然原因。在此后的运行过程中最频繁的操作是一个和系统定时发送握手消息的线程,猜想问题必然出在此线程。首先通过关闭此线程运行,发现Agent果然稳定了,马上进入握手线程的检查,未发现与死机相关的内存问题,开始有些疑惑了!但是问题现象有明显与此线程有关,终于想到既然是握手线程必然要调用消息线程来发送消息,通过对同异步消息线程的分析终于找到问题的真正根源。
问题原因如下:线程A接收消息后如果是异步消息直接发送;如果是同步消息则在发送后将此消息添加到线程B的消息队列,当线程B接收到回复消息后通过设置Event通知线程A。同时线程B还要负责循环检测请求队列中的同步消息是否超时,如果超时则设置Event通知A消息超时。
下面产生问题的关键代码,线程B处理回复消息方法:
int ReqList::Answer(SysMsg* response)
{
//回复消息的处理,其中pReq为A添加到B同步请求消息的指针,dwSeq序列号
  SetEvent(pReq->handle);
  RemoveReq(pReq->dwSeqID);
 }
A,B两线程之间通过设置Event实现同步,而且还通过指针来共享数据结构,这样当B线程设置Event, A得到消息后完成同步消息处理并且会删除pReq,这样当调用RemoveReq 时,可能pReq已经被删除,pReq->dwSeqID为一个无意义的值,可能在请求队列不能找到消息pReq->dwSeqID不能删除此消息,当超时时间到达后Check()必然认为此消息已经超时,这样就会通过指针pReq修改此消息的超时标志,而实际上此消息已被A删除,所以可能引起死机。
阅读(717) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~