【发布时间】:2021-08-03 01:40:56
【问题描述】:
我已将我的 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 中获取相关信息,我们将不胜感激。就像我说的,如果我不注册跟踪处理程序,它工作正常,但如果我这样做,它会挂在快板代码上。
欢迎提供建议和调试技巧。请并感谢您帮助我。 马克
【问题讨论】:
-
每次对 EnterCriticalSection 的调用都需要一个对应的 LeaveCriticalSection (最好使受保护的路径尽可能短)。没有代码就可以说的一切。
-
“欢迎提供建议和调试技巧。” - 放弃 GDB 和跟踪。请改用真正的调试器,例如 WinDbg。从挂起的进程中拉出一个小型转储,让调试器向您显示锁定周期。使用时间旅行调试作为一种有效且高效的方式来确定您是如何结束的。
-
@IInspectable WinDbg 不适用于 MinGW,我不使用 VS,但感谢您的建议。我将在未来将其作为一个选项保持打开状态。
-
MinGW 不允许您生成与 Windows 兼容的 PDB 吗?我想这就是你所需要的。
标签: c debugging winapi allegro5