运行regsvr32.exe时,带有线程句柄的WaitForSingleObject卡住了

时间:2011-07-24 18:54:59

标签: c++ multithreading winapi synchronization waitforsingleobject

我有线程A正在创建另一个线程B,而线程A正在等待使用WaitForSingleObject等待线程B死亡。

问题是即使线程B从线程的“thread_func”返回,线程A 也不会发出信号!

我知道因为我将trace(OutputDebugString)添加到thread_func(线程B的主函数)的末尾,我可以看到线程B完成了它的执行,但是线程A永远不会出现在WaitForSingleObject中。

现在,我还必须补充一点,这个代码是在一个COM对象中,当我调用regsvr32.exe(它被卡住了!)时,上面描述的场景正在发生,所以我相信线程A来自于的DLLMain。

为什么线程A没有发出信号的任何想法?!?!

2 个答案:

答案 0 :(得分:14)

你可能遇到装载机锁的问题。 Windows,有一个内部关键部分,无论何时加载/卸载DLL或线程启动/停止(DllMain总是在该锁内部调用),它都会被锁定。如果您的等待线程A已将该关键部分锁定(即您正在等待DllMain的某个地方),而另一个线程B尝试关闭并尝试获取该加载器关键部分,则会出现死锁。

要查看死锁发生的位置,只需从VS IDE调试器运行您的应用程序,然后在它被卡住后,中断执行。然后查看所有正在运行的线程,并记下每个线程的堆栈。您应该能够跟踪每个堆栈并查看每个线程正在等待的内容。

答案 1 :(得分:4)

我认为@DXM是对的。关于你在DllMain内可以做什么或不能做什么的文档是稀疏的,很难找到,但最重要的是你通常应该把它保持在最低限度 - 初始化内部变量等等,但是就是这个。

我要做的另一点是你通常应该“调用”regsvr32.exe - 永远。

RegSvr32基本上只是一个使用LoadLibrary将DLL加载到其地址空间的包装器,调用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. 
}