网上资料:
进程创建的时候,会创建一把锁,用于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创建的线程退出呢?
谢谢高手

解决方案 »

  1.   

    问题1:
    我在DllMian的DLL_PROCESS_ATTACH中调用LoadLibrary函数,加载另外一个DLL,按照上面的解释,LoadLirary函数内部会调用加载DLL的DllMain函数,应该也会使用到进程的序列化锁,但是为什么不会导致死锁?
    答:LoadLirary是会调用DllMain函数,但是调用的是 他要载入的那个dll的DllMain函数
        比如:LoadLirary(“abc.dll”),调用的是abc.dll的DllMain函数
      

  2.   

    请问,DLL被释放的时候,我应该在什么地方保证DLL创建的线程退出呢?在 DLL_PROCESS_DETACH 时保证
      

  3.   


    在Dll的DLL_PROCESS_DETACH中进行保证的话,调用WaitforsignleObject等待线程退出会导致死锁,帖子里面已经提及了
      

  4.   

    我知道,但是按照网上的资料,只要调用DllMain函数,都回获取进程的序列化锁,这样不会导致死锁吗?
      

  5.   

    一个DllMain一个锁,两个锁互不相关,怎么会死锁
      

  6.   

    会死锁 的,你测试下就知道。
    可以参考一下这篇资料:http://it.china-b.com/ejks/c/20100130/186752_1.html
      

  7.   

    你确信你看明白了这篇文章吗?网上资料:
    进程创建的时候,会创建一把锁,用于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处于同一个线程,不存在互斥量占用的问题了。所以不会死锁。
      

  8.   

    问题2:我开发了一个DLL,DLL有一个Start函数,该函数内部启动了N个线程。另外DLL有一个Stop函数,该函数是停止这N个线程,如果别人拿到我这个DLL,只是调用Start函数,而没有调用Stop函数就调用FreeLibrary函数,就会有可能导致异常,本想在DllMian的DLL_PROCESS_DEATCH中调用Stop函数确保线程退出,但是按照网上的解释,线程退出的时候,会获取进程的序列化锁,而这把锁正被当前的DllMian函数的线程拥有,这样就会死锁。请问,DLL被释放的时候,我应该在什么地方保证DLL创建的线程退出呢?
    谢谢高手
    ============
    还是应该在DLL_PROCESS_DEATCH中处理,你上面理解有误,文章中所说的死锁是出现在DllMain中创建子线程中才出现的。
      

  9.   


    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中等待退出的线程是会死锁的。
      

  10.   

    谢谢回答,即使是在同一个线程,在调用DllMain前,是否需要获取锁呢?据我锁知,关键代码区和Mutex是可以在一个线程中重复获取的,但是我用windbg反汇编的时候,发现系统用的锁是Event 自动锁,这种锁是不能在同一个线程中重复拥有的
      

  11.   

    在DllMian中等待退出的线程是会死锁的
    ========
    你上面的死锁的原因就是因为有两个线程之间互相等待造成的。
      

  12.   

    1、DllMain中调用wait函数等待其它线程才会造成死锁,加载其它DLL没有问题。
    2、最好不要在DllMain中创建线程和等待线程结束,把相关操作都放到导出函数里面,别人没有按照要求调用相应的函数是别人的问题。
      

  13.   


    谢谢cnzdgs ,能否解释下DllMain中调用LoadLibrary或者FreeLibrary为什么没有问题吗?它不会获取序列化的锁??
      

  14.   

    同一线程可以锁多次,不会死锁,估计是你调试的使用没有看仔细,如果是自动复位的事件,第2次执行时应该不会执行到等待函数。Windows中只有“自旋锁”是不能锁多次的,这种锁通常只在驱动程序中使用。
      

  15.   


    恩,刚确认了一下,用的是自动事件,使用NtWaitForSingleObject来等待,而调用LoadLibrary的时候没有执行等待函数,谢谢cnzdgs !