进程显式加载Dll释放时卡在FreeLibrary

DLL隐式加载时没问题,进程可以正常退出。显式加载时就会卡在FreeLibrary,一运行至FreeLibrary调试器里的调用堆栈就被清空了,进程没有退出,但也不报错,经排查不是线程、指针之类的低级错误,跟自己代码没关系

一种可能是DllMain死锁,但里面什么都没做

    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:break;
    case DLL_THREAD_ATTACH:break;
    case DLL_THREAD_DETACH:break;
    case DLL_PROCESS_DETACH:break;
    }

msdn的文档DllMain entry point

一篇求助贴

一篇博文

 

一种可能是winsocket,DLL里用到了win socket,  一旦建立过连接退出进程就卡FreeLibrary,没有建立连接或者连接失败就没问题

msdn的文档说WSACleanup可能会导致DllMain死锁,但我这并不是

 

尝试通过windbg抓异常,跟VS debug一样的,也是抓不到东西。通过windbg看依赖项

ModLoad: 00007ff7`f5a80000 00007ff7`f5b36000 image00007ff7`f5a80000
ModLoad: 00007ffc`39990000 00007ffc`39ba7000 ntdll.dll
ModLoad: 00007ffc`38500000 00007ffc`385c4000 C:\Windows\System32\KERNEL32.DLL
ModLoad: 00007ffc`37020000 00007ffc`373c6000 C:\Windows\System32\KERNELBASE.dll
ModLoad: 00007ffc`38ed0000 00007ffc`3972b000 C:\Windows\System32\SHELL32.dll
ModLoad: 00007ffc`36e60000 00007ffc`36efa000 C:\Windows\System32\msvcp_win.dll
ModLoad: 00007ffc`36f00000 00007ffc`37011000 C:\Windows\System32\ucrtbase.dll
ModLoad: 00007ffb`859b0000 00007ffb`85f65000 D:\Release\Qt5Gui.dll
ModLoad: 00000000`6ae70000 00000000`6b3ee000 D:\Release\Qt5Core.dll
ModLoad: 00000000`6b3f0000 00000000`6b945000 D:\Project\RayoptoDetector\x64\Release\Qt5Widgets.dll
ModLoad: 00007ffc`37cc0000 00007ffc`37e6e000 C:\Windows\System32\USER32.dll
ModLoad: 00007ffc`36cd0000 00007ffc`36cf6000 C:\Windows\System32\win32u.dll
ModLoad: 00007ffc`37840000 00007ffc`37869000 C:\Windows\System32\GDI32.dll
ModLoad: 00007ffc`37450000 00007ffc`37568000 C:\Windows\System32\gdi32full.dll
ModLoad: 00000000`6ae10000 00000000`6ae63000 D:\Release\Qt5Svg.dll
ModLoad: 00007ffc`38640000 00007ffc`387e0000 C:\Windows\System32\ole32.dll
ModLoad: 00007ffc`38170000 00007ffc`384f9000 C:\Windows\System32\combase.dll
ModLoad: 00007ffc`37ac0000 00007ffc`37bd7000 C:\Windows\System32\RPCRT4.dll
ModLoad: 00007ffc`0f8a0000 00007ffc`0f98f000 C:\Windows\SYSTEM32\MSVCR120.dll
ModLoad: 00007ffc`0bea0000 00007ffc`0bf46000 C:\Windows\SYSTEM32\MSVCP120.dll
ModLoad: 00007ffc`36910000 00007ffc`3691a000 C:\Windows\SYSTEM32\VERSION.dll
ModLoad: 00007ffb`7e2f0000 00007ffb`80e58000 D:\Release\opencv_world310.dll
ModLoad: 00007ffc`37790000 00007ffc`37837000 C:\Windows\System32\msvcrt.dll
ModLoad: 00007ffc`37be0000 00007ffc`37cb7000 C:\Windows\System32\OLEAUT32.dll
ModLoad: 00007ffc`30160000 00007ffc`3020b000 C:\Windows\SYSTEM32\UxTheme.dll
ModLoad: 00007ffc`302a0000 00007ffc`302cb000 C:\Windows\SYSTEM32\dwmapi.dll
ModLoad: 00007ffc`38db0000 00007ffc`38ea9000 C:\Windows\System32\COMDLG32.dll
ModLoad: 00007ffc`37f30000 00007ffc`38023000 C:\Windows\System32\shcore.dll
ModLoad: 00007ffc`38030000 00007ffc`3808e000 C:\Windows\System32\SHLWAPI.dll
ModLoad: 00007ffc`387e0000 00007ffc`38893000 C:\Windows\System32\ADVAPI32.dll
ModLoad: 00007ffc`376e0000 00007ffc`37788000 C:\Windows\System32\sechost.dll
ModLoad: 00007ffc`36e30000 00007ffc`36e58000 C:\Windows\System32\bcrypt.dll
ModLoad: 00007ffc`1cb40000 00007ffc`1cbf3000 C:\Windows\WinSxS\amd64_microsoft.windows.common-controls_6595b64144ccf1df_5.82.22621.2506_none_b43bab19638c9595\COMCTL32.dll
ModLoad: 00007ffc`161a0000 00007ffc`161cb000 C:\Windows\SYSTEM32\MSVFW32.dll
ModLoad: 00007ffc`17140000 00007ffc`1715a000 C:\Windows\SYSTEM32\AVICAP32.dll
ModLoad: 00007ffc`02af0000 00007ffc`02b14000 C:\Windows\SYSTEM32\AVIFIL32.dll
ModLoad: 00007ffc`2a8f0000 00007ffc`2a924000 C:\Windows\SYSTEM32\WINMM.dll
ModLoad: 00007ffb`af020000 00007ffb`af03e000 C:\Windows\SYSTEM32\MSACM32.dll
ModLoad: 0000019e`cd210000 0000019e`cd244000 C:\Windows\SYSTEM32\WINMM.dll
ModLoad: 00007ffc`38d30000 00007ffc`38da1000 C:\Windows\System32\WS2_32.dll
ModLoad: 00007ffc`0cdf0000 00007ffc`0ce0e000 C:\Windows\SYSTEM32\MPR.dll
(52d8.5394): Break instruction exception - code 80000003 (first chance)
ntdll!LdrpDoDebuggerBreak+0x30:
00007ffc`39a6b784 cc int 3
0:000> g
ModLoad: 00007ffc`37a80000 00007ffc`37ab1000 C:\Windows\System32\IMM32.DLL
ModLoad: 00007ffc`36460000 00007ffc`3646c000 C:\Windows\SYSTEM32\CRYPTBASE.DLL
ModLoad: 00007ffc`373d0000 00007ffc`3744a000 C:\Windows\System32\bcryptPrimitives.dll
ModLoad: 00007ffb`d7f50000 00007ffb`d809f000 D:\Release\platforms\qwindows.dll
ModLoad: 00007ffc`35d90000 00007ffc`35da8000 C:\Windows\SYSTEM32\kernel.appcore.dll
ModLoad: 00007ffc`34bd0000 00007ffc`354c6000 C:\Windows\SYSTEM32\windows.storage.dll
ModLoad: 00007ffc`34a90000 00007ffc`34bce000 C:\Windows\SYSTEM32\wintypes.dll
ModLoad: 00007ffc`36c00000 00007ffc`36c26000 C:\Windows\SYSTEM32\profapi.dll
ModLoad: 00007ffc`33f50000 00007ffc`341c4000 C:\Windows\system32\dwrite.dll
ModLoad: 00007ffb`f1d30000 00007ffb`f1d78000 D:\Release\MyDll.dll
ModLoad: 00007ffb`e8cf0000 00007ffb`e8d13000 C:\Windows\SYSTEM32\VCOMP120.DLL
ModLoad: 00007ffb`e81b0000 00007ffb`e81ef000 D:\Release\imageformats\qjpeg.dll
ModLoad: 00007ffc`0b2f0000 00007ffc`0b2fc000 D:\Release\imageformats\qsvg.dll
ModLoad: 00007ffc`39730000 00007ffc`39881000 C:\Windows\System32\MSCTF.dll
ModLoad: 00007ffc`37e80000 00007ffc`37f30000 C:\Windows\System32\clbcatq.dll
ModLoad: 00007ffc`03eb0000 00007ffc`03f0e000 C:\Windows\system32\dataexchange.dll
ModLoad: 00007ffc`26c70000 00007ffc`26ef7000 C:\Windows\system32\twinapi.appcore.dll
clientcore\windows\advcore\ctf\uim\tim.cpp(800)\MSCTF.dll!00007FFC397465D9: (caller: 00007FFC3974720C) LogHr(1) tid(5394) 8007029C 出现声明故障。
clientcore\windows\advcore\ctf\uim\tim.cpp(800)\MSCTF.dll!00007FFC397465D9: (caller: 00007FFC3974720C) LogHr(2) tid(5394) 8007029C 出现声明故障。
ModLoad: 00007ffc`27140000 00007ffc`2728a000 C:\Windows\SYSTEM32\textinputframework.dll
ModLoad: 00007ffc`04060000 00007ffc`040ab000 C:\Windows\system32\ApplicationTargetedFeatureDatabase.dll
ModLoad: 00007ffc`36210000 00007ffc`36279000 C:\Windows\system32\mswsock.dll

只要多了这个C:\Windows\system32\mswsock.dll就不行

 

VS debug单步调试,进入FreeLibrary,卡在了C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\crt\src\crtdll.c的这个地方:

__declspec(noinline)
BOOL __cdecl
__DllMainCRTStartup(
        HANDLE  hDllHandle,
        DWORD   dwReason,
        LPVOID  lpreserved
        )
{
...
            if ( (dwReason == DLL_PROCESS_DETACH) ||
                 (dwReason == DLL_THREAD_DETACH) ) {
                if ( _CRT_INIT(hDllHandle, dwReason, lpreserved) == FALSE ) {  //单步进去
                    retcode = FALSE ;
                }

                if ( retcode && _pRawDllMain ) {
                    retcode = (*_pRawDllMain)(hDllHandle, dwReason, lpreserved);
                }
            }
        } __except ( __CppXcptFilter(GetExceptionCode(), GetExceptionInformation()) ) {
            retcode = FALSE;
        }
    } __finally
...
}


BOOL WINAPI _CRT_INIT(
        HANDLE  hDllHandle,
        DWORD   dwReason,
        LPVOID  lpreserved
        )
{
...
        else if ( dwReason == DLL_PROCESS_DETACH )
        {
...
                        /* cache the function to call. */
                        function_to_call = (_PVFV) DecodePointer(*onexitend);

                        /* mark the function pointer as visited. */
                        *onexitend = (_PVFV)EncodePointer(NULL);

                        /* call the function, which can eventually change __onexitbegin and __onexitend */
                        (*function_to_call)();   //该函数不返回

                        onexitbegin_new = (_PVFV *) DecodePointer(__onexitbegin);
                        onexitend_new = (_PVFV *) DecodePointer(__onexitend);
...
}

 

调试看上面的function_to_call,刚好指向一个单例类的析构函数,这个类里面开了一个线程,就是这里了!卡在了std::thread::join()

我这里是常规的线程控制,看着没问题

void MyClass::StopThread()
{
    m_runningFlag = fale;
    if (thread->joinable())  thread->join();
...
}

void MyClass::ThreadFunc()
{
    while(m_runningFlag)
    {
         ...
    }
}

单例类如下

    virtual MyClass::~MyClass()
    {

     StopThread();

    }

    static MyClass* GetInstance()
    {
        static MyClass _instance;
        return &_instance;
    }

难道是因为静态变量,在显式调用DLL时显现出来了,隐式调用静态变量的释放时机不同?

改为在FreeLibrary之前停止线程就可以了

基于 VS2013

posted @ 2024-03-05 00:10  kelvin_yan  阅读(22)  评论(0编辑  收藏  举报