In our project we're using log4cplus indirectly: It is being used in a library that we statically link to, and that project is normally also compiled as a static lib and liked to from our executable. Everything here is Windows and Visual Studio based.
As we've been experiencing problem with application shutdown, I found that we must initialize log4cplus in our main()
function, which solved the problem.
However, the application we're maintaining is - unfortunately - based on ACF (Advanced Component Framework). That means, the static lib (that links to the static lib that links to log4cplus) can be once more linked with a DLL that is then loaded by an application called Compositor during design time. (In Compositor, we can create the target application - which uses the static lib - in a high-level "component-based" fashion...). Now, the problem is that the Compositer would not close properly any more.
When it hangs after closing the main window, we can see the following callstack:
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++
In order to make Compositor close properly, I intorduced a DllMain
function:
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;
}
Now, the application would no longer start but hang at the call to 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++
If I remove that call, startup is normal but the hanging behavior, i.e. Compositer not closing, remains, regardless of threadCleanup()
, Logger::shutdown()
and deinitialize()
(I've tried all combinations).
How can I shutdown log4cplus in a DLL so that the application can terminate properly?