一次Mutex死锁的原因探究
1、现象
最近项目中调出一个bug,某些时候程序会卡死不动,用windbg进行加载后用 ~*kb 命令列出所有的线程栈调用,发现有多个线程调用 WaitForMultipleObjects 在等待同一个内核对象:
输入 !handle cc f 命令列出该内核对象的详细信息:
发现是是一个Mutex对象,对象名是 Mutex_DebugMsg2 ,查找代码知道这个Mutex是用写log时锁定文件写入用的。代码如下:
BOOL CDebugMsg::WriteLogA(LPSTR pszLog)
{
#ifdef _WRITEDEBUGMSGLOG
BOOL bRet = FALSE; if (WaitForSingleObject(m_hMutex, INFINITE) != WAIT_OBJECT_0)
{
return bRet;
} FILE* fp = _tfopen(m_ptszLogPath, _T("a+"));
if (fp)
{
TCHAR ptszTime[16] = {0};
char pszWriteMsg[MAXDEBUGMSGCHARNUM] = {0}; GetTimeString(ptszTime); USES_CONVERSION;
_snprintf(pszWriteMsg, MAXDEBUGMSGCHARNUM, "%s %s\n", T2A(ptszTime), pszLog);
fputs(pszWriteMsg, fp);
fclose(fp);
bRet = TRUE;
} ReleaseMutex(m_hMutex);
return bRet; #endif return FALSE;
}
2、Windbg查找Mutex所有者
为了知道那个线程占用了Mutex没有释放,参考此篇文章说明(http://blog.csdn.net/gufeng99/article/details/46714711)
同时,为了简化问题原因查找,写了小Demo起3个线程调用log记录代码,触发上述bug,后开启windbg进入内核调试模式。
2.1 查看测试Demo进程
2.2 查看进程的所有线程及等待状态信息
发现有3个线程都在等待同一个Mutex,线程所有者是0xfffffa8004d1b590
2.3 查看Mutex所有者线程信息,看是那个线程在占用
找到该线程所在进程的PID = 0xC30,也就是本进程,线程ID = 0xD74
2.4 停止内核附加,切换Windbg改用用户态调试附加Demo进程,列出所有线程信息及调用栈
发现线程拥有者就是主线程,难道是主线程调用后未释放成功么?为了验证这个情况,于是在ReleaseMutex(m_hMutex)加上返回跟踪输出,结果每次释放都是成功的。再看看代码,可能的解释不多了,想得到的可能就是WaitForSingleObject返回了,但返回值不是WAIT_OBJECT_0,导致没有调用ReleaseMutex进行释放。于是再跟踪了下WaitForSingleObject的返回值,发现第一次调用时返回值是128。
去翻了下《windows核心编程》一书,原来Mutex和其他内核对象不一样,当拥有Mutex的线程未进行释放时被终止,这时Mutex处于被废弃状态,其他线程WaitForSingleObject可立即获得Mutex的所有权,但返回值会是WAIT_ABANDONED(128),而并不是WAIT_OBJECT_0,这是Mutex非常特殊的一点。
到了这里,原因就非常明了了,由于log输出在项目中使用非常频繁,而写log时又需要重复调用fopen()和fclose打开关闭文件,这对IO的操作是比较费时间的,导致某些线程在此处由于等待超时被终止(由于其他Mutex是可跨进程的,所以其他进程中的线程意外终止或进程未正常退出都会有此问题),进而导致Mutex未被释放处于废弃状态。而程序收到WAIT_ABANDONED后未是Mutex进行释放,导致Mutex死锁。这里再次深刻的警示,线程是不能随意终止的,同时频繁打开关闭文件操作也是不合理的,正确的做法应该是打开一次后保存文件句柄,再程序退出时再关闭。
另由于这个bug不是必现(由于线程不是每次都会由于等待超时被终止),在调试过程中我保存了下dump,后来调试下dump的时候显示handle信息是发现一个非常有意思的事情:
dump中在调用 !handle cc f 命令后,同时也将Mutex的拥有者线程也显示出来了,而在即时调试的时候却没有该信息,需要绕一圈到内核中去查找。
一次Mutex死锁的原因探究的更多相关文章
- 查询在应用程序运行得很慢, 但在SSMS运行得很快的原因探究
原文:查询在应用程序运行得很慢, 但在SSMS运行得很快的原因探究 查询在应用程序运行得很慢, 但在SSMS运行得很快的原因探究 -理解性能疑点 1 引言 内容来自http://www.so ...
- java中多线程产生死锁的原因以及解决意见
1. java中导致死锁的原因 多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放,而该资源又被其他线程锁定,从而导致每一个线程都得等其它线程释放其锁定的资源,造成了所有线程都无法正常结 ...
- SQL Server死锁产生原因及解决办法 .
其实所有的死锁最深层的原因就是一个:资源竞争 表现一: 一个用户A 访问表A(锁住了表A),然后又访问表B,另一个用户B 访问表B(锁住了表B),然后企图访问表A,这时用户A由于用户B已经锁住表B,它 ...
- java 死锁产生原因及解锁(转)
原文地址 进程死锁及解决办法 一.要点提示 (1) 掌握死锁的概念和产生死锁的根本原因. (2) 理解产生死锁的必要条件--以下四个条件同时具备:互斥条件.不可抢占条件.占有且申请条件.循环等待条件. ...
- 使用JDK自带的工具jstack找出造成运行程序死锁的原因
Java多线程编程也是Java面试中经常考察的内容.刚接触Java多线程编程的朋友们,可能会不慎写出一些会导致死锁(deadlock)的应用出来.如何分析造成Java多线程的原因呢?很多时候我们在怀疑 ...
- 谁在死锁Mutex——用Windbg查找Mutex死锁所有者线程
Who is blocking that Mutex? - Fun with WinDbg, CDB and KD 05 Aug 2006 By Ingo Rammer I'm currently t ...
- MSSQL死锁产生原因及解决方法
一. 什么是死锁 死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等的进 ...
- nignx+php-fpm环境下 phpmyadmin打开空白的原因探究
打开phpmyadmin一直是空白的,发现是js的问题,原因是pma的js/get_script_js.php读取js不完整 很容易的将问题原因想到了php的输出缓存大小上,我把php.ini里的ou ...
- Windbg调试互斥体(Mutex)死锁
一. 测试代码 #include <windows.h> #include <tchar.h> #include <process.h> HANDLE hMutex ...
随机推荐
- Sortable – 简单灵活的 JavaScript 拖放排序插件
当需要在网站中添加拖放排序功能的时候,jQuery UI 的排序组件可能是最流行的解决方案.今天给大家介绍另一款简单灵活的 JavaScript 拖放排序插件——Sortable,它使用 HTML5 ...
- .Net资源总结
源码文档见官方群(以下为7.4更新内容) 逆天工具 CDN 资源库 国内 Bootstrap中文网开源项目免费 CDN 服务 360网站卫士常用前端公共库CDN服务 百度静态资源公共库 新浪云计算CD ...
- HTML标签的嵌套规则
我在平时在写html文档的时候,发现不太清楚标签之间的嵌套规则,经常是想到什么标签就用那些,后来发现有些标签嵌套却是错误的.通过网上找资料,了解了html标签的嵌套规则. 一.HTML 标签包括 块级 ...
- SharePoint 2013 搜索报错"Unable to retrieve topology component health. This may be because the admin component is not up and running"
环境描述 Windows 2012 R2,SharePoint 2013(没有sp1补丁),sql server 2012 错误描述 搜索服务正常,但是爬网一直在Crawling Full,但是爬不到 ...
- 编译安装mysql(Ubuntu10 64位)
选用较好的编译器和较好的编译器选项,这样应用可提高性能10-30%,这个对大多数程序都非常重要 Mysql的编译,不同的版本具体的配置方式是有差别的 旧版的配置形式参考 这个形式主要是使用config ...
- SqlIte数据库并发性
把遇到的一些小问题都记下来,告诉自己,一些小细节会铸成打错的 今天没事复习以前的知识,用sqlite做数据库,发现修改数据的时候等好久才有反应,而且还失败,可是过一会之后又会好,好了以后又是一样,种以 ...
- JSON解析实例——使用Json-lib
JSON解析实例——使用Json-lib Json-lib下载及使用 本文介绍用一个类库进行JSON解析. 工具下载地址:http://sourceforge.net/projects/json-li ...
- word第二讲(0806)
word里的长度单位 绝对长度单位(厘米,英寸) 相对长度单位(字符,像素) 样式 问题: 如何设置多个部分的格式 多次选择,多次设置 多次选择,一次设置 应用格式刷(ctrl+shift+c,ctr ...
- Android Handler机制(二)---MessageQueue源码解析
MessageQueue 1.变量 private final boolean mQuitAllowed;//表示MessageQueue是否允许退出 @SuppressWarnings(" ...
- gridView获得每行的值
前台代码: <asp:GridView ID="GridView1" runat="server" DataKeyNames="ID" ...