前言
项目里的一个升级程序偶尔会死锁,查看dump
后发现是死在了ShellExecuteExW
里。经验少,不知道为什么,于是在高端调试论坛里发帖求助,链接如下http://advdbg.org/forums/6520/ShowPost.aspx
根据张银奎老师的描述可知,应该是拥有关键段的线程意外结束了。仔细检查项目中的代码,发现程序中有使用TerminateThread()
来强制杀线程的代码。很可疑,于是写了一个测试程序,还原了这个问题。
{% note info %}
这也是几年前在项目中遇到的一个问题,我对之前的笔记进行了整理重新发布于此。
{% endnote %}
问题重现
重现方法
主程序会加载一个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 = LoadLibra