我有线程A正在创建另一个线程B,而线程A正在使用WaitForSingleObject等待,直到线程B死亡。
问题是,即使线程B从线程的"thread_func"返回,线程A 没有得到信号!.
我知道,因为我在thread_func(线程B的主函数)的末尾添加了trace (OutputDebugString),我可以看到线程B完成了它的执行,但线程A永远不会从WaitForSingleObject中出来。
现在,我还必须补充说,这段代码是在一个COM对象中,当我调用regsvr32.exe(它卡住了!)时,上面描述的场景正在发生,所以我相信线程a来自DLLMain。
为什么线程A没有得到信号?
您可能遇到加载器锁的问题。Windows有一个内部临界区,当DLL加载/卸载或线程启动/停止时,该临界区被锁定(DllMain总是在该锁中被调用)。如果你的等待线程A已经锁定了临界区(即你正在等待DllMain的某个地方),而另一个线程B试图关闭并试图获取加载器临界区,你就会死锁。
要查看死锁发生的地方,只需从VS IDE调试器运行你的应用程序,在它卡住后,中断执行。然后查看所有正在运行的线程,并记录每个线程的堆栈。您应该能够跟踪每个堆栈并查看每个线程正在等待的内容。
我认为@DXM是对的。关于在DllMain
中可以做什么或不可以做什么的文档很少,很难找到,但底线是您通常应该将其保持在最低限度——初始化内部变量等,但仅此而已。
我想说的另一点是,你通常应该不"调用"regsvr32.exe——永远。
RegSvr32基本上只是一个包装器,将DLL加载到LoadLibrary
的地址空间中,调用GetProcAddress
以获得名为DllRegisterServer
的函数的地址,然后调用该函数。自己完成这项工作要干净得多(最终也更容易),就像这样:
HMODULE mod = LoadLibrary(your_COM_file);
register_DLL = GetProcAddress(mod, "DllRegisterServer");
if ( register_DLL == NULL) {
// must not really be a COM object...
}
if ( S_OK != register_DLL()) {
// registration failed.
}