WaitForSingleObject与线程句柄卡住,同时运行regsvr32.exe



我有线程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. 
} 

最新更新