如何安全地调用 TerminateThread 和 FreeLibrary (WinAPI, C++)
Posted
技术标签:
【中文标题】如何安全地调用 TerminateThread 和 FreeLibrary (WinAPI, C++)【英文标题】:How to safely call TerminateThread and FreeLibrary (WinAPI, C++) 【发布时间】:2020-12-25 21:18:44 【问题描述】:我曾经通过从使用CreateThread
创建的线程中调用FreeLibraryAndExitThread
来卸载注入的库。
需要从不同的线程卸载库导致这种方法不可能。现在我正在使用TerminateThread
(因为它不会终止调用它的线程,而是通过的线程)和FreeLibrary
。但是,正如 WinAPI 文档所建议的那样,这会产生“竞争条件”并使进程崩溃。有没有办法解决这个问题?
旧代码:
HMODULE g_hModule NULL ;
BOOL WINAPI DllMain(HMODULE hModule, DWORD fwdReason, LPVOID lpReserved)
g_hModule = hModule;
if (fwdReason == DLL_PROCESS_ATTACH)
DisableThreadLibraryCalls(hModule);
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)main, 0, 0, 0);
return TRUE;
void Unload(int nExitCode)
FreeLibraryAndExitThread(g_hModule, (DWORD)nExitCode);
新代码:
HMODULE g_hModule NULL ;
HANDLE g_hThread NULL ;
BOOL WINAPI DllMain(HMODULE hModule, DWORD fwdReason, LPVOID lpReserved)
g_hModule = hModule;
if (fwdReason == DLL_PROCESS_ATTACH)
DisableThreadLibraryCalls(hModule);
g_hThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)main, 0, 0, 0);
return TRUE;
void Unload(int nExitCode)
TerminateThread(g_hThread, (DWORD)nExitCode);
FreeLibrary(g_hModule);
提前感谢您的帮助!
【问题讨论】:
这能回答你的问题吗? Kill a running thread 无论如何,在这里搜索“[c++] 终止线程”,你会发现很多信息。在进一步探索这条道路之前,了解终止线程的含义。 简短回答:不,没有。 C++ 不能以这种方式工作。除了从原始线程函数返回之外,通过任何方式终止线程都是未定义的行为。TerminateThread
没有明确定义的 C++ 代码行为。它不适用于 C++ 代码。
新代码在所有情况下都是错误的并且毫无意义。 TerminateThread
- 你终止了 self 线程。 FreeLibrary
永远不会被调用。没有意义创建线程只是为了终止它(甚至不正确退出)。旧代码看起来是正确的(假设 main == Unload
和错误的卸载签名)
在旧代码中Unload
是从main
(由CreateThread
创建的线程)调用的,而在新代码中它是从一个单独的线程调用的。这就是为什么我认为 FreeLibrary
应该运行
ULONG WINAPI Unload(PVOID) FreeLibraryAndExitThread((HMODULE)&__ImageBase, 0);
和 CreateThread(0, 0, Unload, 0, 0, 0);
这就是代码需要的样子
【参考方案1】:
安全终止线程的唯一方法,尤其是在 C++ 中,是让该线程从传递给 CreateThread
的函数返回。这通常通过设置(比如)一个atomic<bool>
来完成,该线程定期测试以查看它是否应该退出。您还可以使用条件变量(或 Win32 等效项)来唤醒线程,而不是忙循环。
TerminateThread
非常危险,例如,线程可能当时持有某种关键锁(可能是malloc
使用的锁),这会挂起您的应用程序的其余部分。它本来就不应该在 Win32 API 中提供,你不应该使用它。
【讨论】:
但是TerminateThread
与问题有何关联?关于如何从这个 dll 中取消引用 dll 的问题。
OP 想要卸载 dll。绝对与终止线程无关以上是关于如何安全地调用 TerminateThread 和 FreeLibrary (WinAPI, C++)的主要内容,如果未能解决你的问题,请参考以下文章
获取/检查进程 win32 的内部 kernel32 状态(为了安全使用 TerminateThread )
delphi TerminateThread 结束一个线程后内存残留
在 C++ 代码中调用 TerminateThread 后在 C# 代码中检测到 FatalExecutionEngineError
TerminateThread 可以终止另一个进程的线程吗?