c - 为什么我的 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 中获取相关信息的帮助将不胜感激。就像我说的,如果我不注册跟踪处理程序,它工作正常,但如果我这样做,它会挂在快板代码上。
欢迎提供建议和调试技巧。请并感谢您帮助我。马克
解决方案
在使用用户跟踪处理程序的 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;
}
推荐阅读
- python - 将 scikitlearn 预处理应用于 pandas 而不会引起警告
- python - 如何将未知长度列表的元素作为函数的参数?Python
- python - 如何匹配略微偏移的图像?
- python - 您如何使用 pandas 和 python 来评估用户位于多少地理框内?
- javascript - 默认情况下,如何为 map 函数设置一个值?
- react-native - React Native 网格日历,看起来像 Google 日历的月视图
- c++ - 从 Boost 属性树中提取 STL 映射
- c++ - E0349 没有操作符“<<”匹配这些操作数 c++
- google-apps-script - 如何复制整个工作表并将结果粘贴到特定工作表中
- android - 在模拟器上测试对 AOSP 代码(包 android.media)所做的更改