网上资料:
进程创建的时候,会创建一把锁,用于DllMain调用时候的序列化,如果在DllMain中的DLL_PROCESS_ATTACH中创建一个线程,然后等待该线程退出,会导致死锁,原因是线程创建时候需要打开进程的序列化锁,而进程的序列化锁在DLLMain函数没有退出前没有被释放。问题1:
我在DllMian的DLL_PROCESS_ATTACH中调用LoadLibrary函数,加载另外一个DLL,按照上面的解释,LoadLirary函数内部会调用加载DLL的DllMain函数,应该也会使用到进程的序列化锁,但是为什么不会导致死锁?问题2:我开发了一个DLL,DLL有一个Start函数,该函数内部启动了N个线程。另外DLL有一个Stop函数,该函数是停止这N个线程,如果别人拿到我这个DLL,只是调用Start函数,而没有调用Stop函数就调用FreeLibrary函数,就会有可能导致异常,本想在DllMian的DLL_PROCESS_DEATCH中调用Stop函数确保线程退出,但是按照网上的解释,线程退出的时候,会获取进程的序列化锁,而这把锁正被当前的DllMian函数的线程拥有,这样就会死锁。请问,DLL被释放的时候,我应该在什么地方保证DLL创建的线程退出呢?
谢谢高手
进程创建的时候,会创建一把锁,用于DllMain调用时候的序列化,如果在DllMain中的DLL_PROCESS_ATTACH中创建一个线程,然后等待该线程退出,会导致死锁,原因是线程创建时候需要打开进程的序列化锁,而进程的序列化锁在DLLMain函数没有退出前没有被释放。问题1:
我在DllMian的DLL_PROCESS_ATTACH中调用LoadLibrary函数,加载另外一个DLL,按照上面的解释,LoadLirary函数内部会调用加载DLL的DllMain函数,应该也会使用到进程的序列化锁,但是为什么不会导致死锁?问题2:我开发了一个DLL,DLL有一个Start函数,该函数内部启动了N个线程。另外DLL有一个Stop函数,该函数是停止这N个线程,如果别人拿到我这个DLL,只是调用Start函数,而没有调用Stop函数就调用FreeLibrary函数,就会有可能导致异常,本想在DllMian的DLL_PROCESS_DEATCH中调用Stop函数确保线程退出,但是按照网上的解释,线程退出的时候,会获取进程的序列化锁,而这把锁正被当前的DllMian函数的线程拥有,这样就会死锁。请问,DLL被释放的时候,我应该在什么地方保证DLL创建的线程退出呢?
谢谢高手
我在DllMian的DLL_PROCESS_ATTACH中调用LoadLibrary函数,加载另外一个DLL,按照上面的解释,LoadLirary函数内部会调用加载DLL的DllMain函数,应该也会使用到进程的序列化锁,但是为什么不会导致死锁?
答:LoadLirary是会调用DllMain函数,但是调用的是 他要载入的那个dll的DllMain函数
比如:LoadLirary(“abc.dll”),调用的是abc.dll的DllMain函数
在Dll的DLL_PROCESS_DETACH中进行保证的话,调用WaitforsignleObject等待线程退出会导致死锁,帖子里面已经提及了
可以参考一下这篇资料:http://it.china-b.com/ejks/c/20100130/186752_1.html
进程创建的时候,会创建一把锁,用于DllMain调用时候的序列化,如果在DllMain中的DLL_PROCESS_ATTACH中创建一个线程,然后等待该线程退出,会导致死锁,原因是线程创建时候需要打开进程的序列化锁,而进程的序列化锁在DLLMain函数没有退出前没有被释放。
=====================
这里产生死锁的原因是:LoadLibrary时,会调用DllMain,此时DllMain会产生一个线程,然后等待,注意,此时,DllMain并没有结束,它还没有完成,而是在等待新线程结束。所以此时,互斥量被占用着,因为每新生成一个线程,DllMain都要被调用一次,此时由于互斥量被占用,所以第二个线程又被阻住了,它在等第一个主线程对DllMain的调用结束,但第一个主线程在DllMain中又是等待着第二个线程结束的。所以死锁出现了。问题1:
我在DllMian的DLL_PROCESS_ATTACH中调用LoadLibrary函数,加载另外一个DLL,按照上面的解释,LoadLirary函数内部会调用加载DLL的DllMain函数,应该也会使用到进程的序列化锁,但是为什么不会导致死锁?
===================
你在DLL_PROCESS_ATTACH中调用LoadLibrary,加载另一个DLL,而会调用另一个DLL的DllMain,但是与上面不同的是,你这里只有一个线程,另一个DLL的DllMain并不是执行在新的线程中的,而是和LoadLibrary处于同一个线程,不存在互斥量占用的问题了。所以不会死锁。
谢谢高手
============
还是应该在DLL_PROCESS_DEATCH中处理,你上面理解有误,文章中所说的死锁是出现在DllMain中创建子线程中才出现的。
DWORD _stdcall ThreadProc(void *pPar)
{
WaitForSingleObject(g_hEvent,INFINITE);
OutputDebugString("exit");
return 0;
}
BOOL StartThread()
{
g_hThread = CreateThread(NULL,0,ThreadProc,NULL,0,NULL);
return TRUE;
}
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch( ul_reason_for_call )
{
case DLL_PROCESS_ATTACH :
{
DisableThreadLibraryCalls((HMODULE)hModule);
g_hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
break;
}
case DLL_PROCESS_DETACH:
{
SetEvent(g_hEvent);
WaitForSingleObject(g_hThread,INFINITE);等待线程退出,会卡死
OutputDebugString("a");
break;
}
case DLL_THREAD_DETACH:
{
break;
}
default:
{
break;
} }
return TRUE;
}
在DllMian中等待退出的线程是会死锁的。
========
你上面的死锁的原因就是因为有两个线程之间互相等待造成的。
2、最好不要在DllMain中创建线程和等待线程结束,把相关操作都放到导出函数里面,别人没有按照要求调用相应的函数是别人的问题。
谢谢cnzdgs ,能否解释下DllMain中调用LoadLibrary或者FreeLibrary为什么没有问题吗?它不会获取序列化的锁??
恩,刚确认了一下,用的是自动事件,使用NtWaitForSingleObject来等待,而调用LoadLibrary的时候没有执行等待函数,谢谢cnzdgs !