在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
相关产品推荐
相关产品推荐

