这是继上一篇 [原]调试DLL卸载时的死锁 后的又一篇使用windbg调试死锁的文章。希望能对大家有所帮助。
前言
之前项目里的一个升级程序偶尔会死锁,查看dump后发现是死在了ShellExecuteExW里。经验少,不知道为什么,于是在高端调试论坛里发帖求助,链接如下 http://advdbg.org/forums/6520/ShowPost.aspx
根据张银奎老师的描述可知,应该是拥有关键段的线程意外结束了。仔细检查项目中的代码,发现程序中有使用TerminateThread()来强制杀线程的代码。很可疑,于是写了一个测试程序,还原了这个问题。
问题重现
重现方法
主程序会加载一个DLL,并调用该DLL的导出函数创建一个线程,然后调用TerminateThread()强制杀死这个线程,然后调用RunProcess()(内部封装了对ShellExecuteEx()的调用)执行一个新进程,会卡死在ShellExecuteEx()。为了让问题更容易重现,特地在DllMain()的参数ul_reason_for_call为DLL_THREAD_DETACH时,强制睡眠了5秒。
代码摘录
主工程 testTerminateThread
//testTerminateThread.cpp
#include "stdafx.h"
#include "windows.h"
#include "process.h"
typedef HANDLE (*pfnGenerateThread)();
HANDLE RunProcess(const TCHAR* app_name, const TCHAR* cmd)
{
SHELLEXECUTEINFO shex = {sizeof(SHELLEXECUTEINFO)};
shex.fMask = SEE_MASK_NOCLOSEPROCESS;
shex.lpVerb = _T("open");
shex.lpFile = app_name;
shex.lpParameters = cmd;
shex.lpDirectory = NULL;
shex.nShow = SW_NORMAL;
if (!::ShellExecuteEx(&shex))
{
return INVALID_HANDLE_VALUE;
}
return shex.hProcess;
}
int _tmain(int argc, _TCHAR* argv[])
{
while ( 1 )
{
HMODULE hModule = LoadLibrary(_T("testDll.dll"));
if ( NULL == hModule )
return 0;
pfnGene

本文介绍了在项目中遇到的由TerminateThread导致的死锁问题,详细分析了问题的重现方法、代码示例及解决思路。通过调试工具揭示了线程在被终止前持有关键段导致的死锁现象,提醒开发者避免随意使用TerminateThread。
最低0.47元/天 解锁文章
1万+

被折叠的 条评论
为什么被折叠?



