首页 > 解决方案 > 为什么我的 CRITICAL_SECTION 的 RecursionCount 这么大?调试死锁

问题描述

我已将 Eagle GUI 库与 Allegro 5 结合用于图形和输入。当我使用 Allegro 5 的al_register_trace_handler函数将 allegro 调试日志的输出通过管道传输到我自己的时,我在 allegro 生成的线程中出现死锁,以创建一个 win32 窗口和显示。ALLEGRO_INFO它专门挂在allegro 使用的日志记录宏的调用上。用于防止日志中竞争条件的 CRITICAL_SECTION 显示为由我的主线程持有。当我在 gdb 中输出 CRITICAL_SECTION 时,我得到以下报告:

(gdb) p *(trace_info.trace_mutex.cs)
$1 = {DebugInfo = 0xffffffff, LockCount = -2, RecursionCount = 176, OwningThread = 0x4750, LockSemaphore = 0x0, SpinCount = 33556432}

线程 4750 是主线程,由 gdb 和 info 线程标识。如果我没有向 allegro 注册跟踪处理程序,一切正常,但如果我这样做了,并且我使用了“调试”或“信息”的调试级别,它会在提到的日志输出调用中死锁。我发现在注册的跟踪处理程序的情况下,allegro 跟踪函数没有释放 CRITICAL_SECTION,我认为可以通过释放锁来修复它,但它什么也没做,输出保持不变。

临界区 ReferenceCount 字段的值是否表示未能正确解锁日志的互斥体(CS),为什么锁仍然由主线程持有?

我的调试技能已经接近尾声了。我记录了我自己所有线程的状态,并且没有一个线程处于争用状态。但是,main 持有 allegro 在不同线程中使用的 CRITICAL_SECTION 的事实似乎表明我做错了什么。

因此,任何从 allegro 和 gdb 中获取相关信息的帮助将不胜感激。就像我说的,如果我不注册跟踪处理程序,它工作正常,但如果我这样做,它会挂在快板代码上。

欢迎提供建议和调试技巧。请并感谢您帮助我。马克

标签: cdebuggingwinapiallegro5

解决方案


在使用用户跟踪处理程序的 allegro 代码的路径中遗漏了有问题的缺失 LeaveCriticalSection 调用。以下补丁修复了该问题。

--- C:/Users/Marc/AppData/Local/Temp/TortoiseGit/debug-619c69e3.002.c   Thu May 13 11:18:03 2021
+++ E:/usr/libs/Allegro52X/src/debug.c  Wed May 12 11:20:57 2021
@@ -300,6 +300,7 @@
    if (_al_user_trace_handler) {
       _al_user_trace_handler(static_trace_buffer);
       static_trace_buffer[0] = '\0';
+      _al_mutex_unlock(&trace_info.trace_mutex);
       return;
    }

推荐阅读