You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在DllMain的DLL_PROCESS_ATTACH中调用sentry_init()死锁如何解决?

死锁根本原因

DllMain执行时系统会持有进程加载器锁,该锁为全局排他锁,会阻塞所有模块加载、线程启停、同步对象申请等操作:

  • sentry_init内部包含大量需要申请加载器锁的操作:启动crashpad_handler子进程、创建后台上报线程、加载系统网络相关DLL、初始化同步对象等,这些操作会等待已经被你持有的加载器锁释放,直接形成死锁。
  • 额外问题:你当前代码在sentry_init执行前就创建Sentry事件、设置堆栈,此时Sentry上下文未初始化,也可能引发未定义行为。
修复方案

方案1(推荐):将Sentry逻辑完全移出DllMain

DllMain仅保留最基础的实例句柄存储逻辑,所有SDK初始化、事件上报逻辑放到自定义导出函数中,由宿主进程在自身业务线程主动调用:

// 头文件添加导出声明
__declspec(dllexport) BOOL SentryDLL_Init() {
    sentry_options_t* options = sentry_options_new();
    sentry_options_set_dsn(options, "mydsn");
    sentry_options_set_release(options, "");
    sentry_options_set_debug(options, 1);
    sentry_options_set_max_breadcrumbs(options, 100);
    sentry_options_set_handler_path(options, "/sentry/crashpad_handler.exe");
    sentry_options_set_environment(options, "DEBUG");

    // 先初始化Sentry
    if (sentry_init(options) != 0) {
        // 初始化失败处理
        return FALSE;
    }

    // 初始化完成后再构造、上报事件
    sentry_value_t exc = sentry_value_new_object();
    sentry_value_set_by_key(exc, "type", sentry_value_new_string("Report"));
    sentry_value_t event = sentry_value_new_event();
    sentry_value_set_by_key(event, "exception", exc);
    sentry_event_value_add_stacktrace(event, nullptr, 0);
    sentry_capture_event(event);

    return TRUE;
}

// 简化后的DllMain
BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
        case DLL_PROCESS_ATTACH:
            g_hInstance = (HINSTANCE)hModule;
            break;
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            break;
    }
    return TRUE;
}

方案2(适配必须自动初始化的场景):延迟异步初始化

如果无法要求宿主调用导出函数,可在DllMain中创建独立线程执行Sentry初始化,线程启动后会等待加载器锁释放后再执行逻辑,避免死锁:

DWORD WINAPI SentryInitThread(LPVOID lpParam) {
    // 此处放置所有Sentry初始化、事件上报逻辑,和方案1的SentryDLL_Init实现一致
    return 0;
}

BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
        case DLL_PROCESS_ATTACH:
            g_hInstance = (HINSTANCE)hModule;
            // 仅创建线程,不做其他操作
            CreateThread(NULL, 0, SentryInitThread, NULL, 0, NULL);
            break;
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            break;
    }
    return TRUE;
}

内容的提问来源于stack exchange,提问作者JuHyeon Lee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 23:54:02