В нашем проекте мы косвенно используем log4cplus: он используется в библиотеке, на которую мы статически ссылаемся, и этот проект обычно также компилируется как stati c lib и ему нравится из нашего исполняемого файла. Все здесь Windows и основано на Visual Studio.
Поскольку у нас возникла проблема с закрытием приложения, я обнаружил, что мы должны инициализировать log4cplus в нашей main()
функции , которая решила проблема.
Однако поддерживаемое нами приложение, к сожалению, основано на ACF ( Advanced Component Framework ). Это означает, что stati c lib (которая ссылается на stati c lib, которая ссылается на log4cplus) может быть снова связана с DLL, которая затем загружается приложением под названием Compositor во время разработки , (В Compositor мы можем создать целевое приложение - которое использует stati c lib - высокоуровневым способом «на основе компонентов» ...). Теперь проблема в том, что Compositer больше не закрывается должным образом.
Когда он зависает после закрытия главного окна, мы можем видеть следующий стек вызовов:
ntdll.dll!NtWaitForAlertByThreadId() + 20 bytes Unknown
ntdll.dll!RtlSleepConditionVariableSRW() + 265 bytes Unknown
KernelBase.dll!SleepConditionVariableSRW() + 45 bytes Unknown
msvcp140.dll!__crtSetThreadpoolWait() + 80 bytes Unknown
msvcp140.dll!_Cnd_timedwait() + 396 bytes Unknown
msvcp140.dll!_Cnd_timedwait() + 84 bytes Unknown
log4cplusUx64.dll!log4cplus::helpers::getFileInfo() + 3473 bytes Unknown
log4cplusUx64.dll!00007ff86917fefb() Unknown
ucrtbase.dll!_execute_onexit_table() + 342 bytes Unknown
ucrtbase.dll!_execute_onexit_table() + 123 bytes Unknown
ucrtbase.dll!_execute_onexit_table() + 52 bytes Unknown
log4cplusUx64.dll!log4cplus::helpers::getFormattedTime() + 5056 bytes Unknown
log4cplusUx64.dll!log4cplus::helpers::getFormattedTime() + 5364 bytes Unknown
ntdll.dll!RtlAnsiStringToUnicodeString() + 663 bytes Unknown
ntdll.dll!LdrShutdownProcess() + 300 bytes Unknown
ntdll.dll!RtlExitUserProcess() + 173 bytes Unknown
kernel32.dll!ExitProcess() + 10 bytes Unknown
ucrtbase.dll!exit() + 468 bytes Unknown
ucrtbase.dll!exit() + 127 bytes Unknown
> Compositor.exe!__scrt_common_main_seh() Line 295 C++
Чтобы правильно закрыть Compositor, я ввел функцию DllMain
:
BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
log4cplus::initialize();
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
log4cplus::threadCleanup();
break;
case DLL_PROCESS_DETACH:
log4cplus::Logger::shutdown();
log4cplus::deinitialize();
break;
}
return TRUE;
}
Теперь приложение больше не будет запускаться, а будет зависать при вызове log4cplus::initialize()
:
ntdll.dll!NtWaitForAlertByThreadId() + 20 bytes Unknown
ntdll.dll!RtlSleepConditionVariableSRW() + 265 bytes Unknown
KernelBase.dll!SleepConditionVariableSRW() + 45 bytes Unknown
msvcp140.dll!__crtSetThreadpoolWait() + 80 bytes Unknown
msvcp140.dll!_Cnd_timedwait() + 396 bytes Unknown
msvcp140.dll!_Cnd_timedwait() + 84 bytes Unknown
log4cplusUx64.dll!00007ff8697360d0() Unknown
log4cplusUx64.dll!00007ff86973625f() Unknown
log4cplusUx64.dll!log4cplus::spi::FactoryRegistry<log4cplus::spi::LocaleFactory>::FactoryRegistry<log4cplus::spi::LocaleFactory>() + 1438 bytes Unknown
log4cplusUx64.dll!log4cplus::initialize() + 194 bytes Unknown
> MePiaPck.arp!DllMain(HINSTANCE__ * __formal, unsigned long fdwReason, void * __formal) Line 46 C++
Если я удалю этот вызов, запуск будет нормальным, но поведение зависания, т.е. Compositer не будет закрытие, остается, независимо от threadCleanup()
, Logger::shutdown()
и deinitialize()
(я пробовал все комбинации).
Как я могу завершить log4cplus в DLL, чтобы приложение могло правильно завершиться?