c语言 - 为什么我的CRITICAL_SECTION的递归计数如此之大?调试死锁



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

关键部分中 ReferenceCount 字段的值是否指示无法正确解锁日志的互斥锁 (CS),为什么锁仍由主线程持有?

我的调试技能即将结束。我记录了我自己的所有线程的状态,没有一个线程处于争用状态。但是,main 在不同的线程中保存 allegro 正在使用的CRITICAL_SECTION这一事实似乎表明我做错了什么。

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

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

在使用用户跟踪处理程序的 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] = '';
+      _al_mutex_unlock(&trace_info.trace_mutex);
return;
}

最新更新