首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在DLL中终止log4cplus?

如何在DLL中终止log4cplus?
EN

Stack Overflow用户
提问于 2020-03-11 10:21:30
回答 1查看 506关注 0票数 1

在我们的项目中,我们间接地使用log4cplus :它在我们静态链接到的库中使用,该项目通常也被编译为静态库,并且喜欢从我们的可执行文件编译。这里的一切都是基于Windows和Visual的。

由于我们一直在经历应用程序关闭的问题,我发现我们必须使用函数来解决这个问题。

然而,我们维护的应用程序--不幸的是--基于ACF (高级组件框架)。这意味着,静态库(链接到链接到log4cplus的静态库)可以再次与DLL链接,然后由名为Compositor的应用程序在设计时加载。(在Compositor中,我们可以以高级的“基于组件的”方式.创建目标应用程序(它使用静态库)。现在,问题是Compositer将不再正确地关闭。

当它在关闭主窗口后挂起时,我们可以看到以下调用堆栈:

代码语言:javascript
复制
    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函数:

代码语言:javascript
复制
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()的调用。

代码语言:javascript
复制
    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() (我已经尝试了所有组合)。

如何在DLL中关闭log4cplus以使应用程序能够正确终止?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-03-24 09:03:00

正如@RbMm的注释中提到的,在DllMain中初始化DllMain的原因是该函数在“加载程序锁”- cf中执行。这里这里.

解决方案是在DLL中找到从加载应用程序的主线程执行的函数,并在那里初始化log4cplus。

对于ACF的Compositor,首先调用的是包导出函数。通常,它作为宏包装在ACF包中,即I_EXPORT_PACKAGE。展开该宏允许输入以下代码:

代码语言:javascript
复制
extern "C" I_FUNCTION_EXPORT icomp::CPackageStaticInfo* I_PACKAGE_EXPORT_FUNCTION()
{
    static bool bFirstLoad = true;
    if (bFirstLoad)
    {
        log4cplus::initialize();
        log4cplus::deinitialize();
        bFirstLoad = false;
    }
    return &packageInfo;
}

在第一次调用包时初始化和取消初始化log4cplus使Compositor应用程序能够正常地关闭和终止。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60633764

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档