确定 Windows 线程是不是在关键部分或类似部分?

Posted

技术标签:

【中文标题】确定 Windows 线程是不是在关键部分或类似部分?【英文标题】:Determine if a Windows thread is in a Critical Section or similar?确定 Windows 线程是否在关键部分或类似部分? 【发布时间】:2015-09-03 16:11:51 【问题描述】:

所以我们有一个断言引擎。

它的作用是创建一个断言辅助线程,暂停所有其他线程,然后在辅助线程中弹出一些交互式 UI 以与用户讨论断言失败。 (我们暂停其他线程,因为我们想要断言失败时程序状态的快照,并且我们不希望其他线程继续前进)。

这在大多数情况下都很好用。

在一小部分时间里,一个被挂起的线程持有一个锁——通常是调试堆临界区——并且断言辅助线程在下一次分配时阻塞(这很难避免)。

我可以看到两种解决方法。首先,取消进程内断言处理(让它启动进程外断言对话框,并使用 IPC 来回通信)。通过这种方式,我们可以在没有堆分配的情况下管理该通信。也许吧。

这是一堆工作,因为这意味着我们必须将进程内的堆栈遍历代码移出进程等。

我们现在尝试的方法是添加一个看门狗线程。它会注意到断言辅助线程是否未能取得进展(可能是发送定时器消息失败,可能它的指令计数器停止移动;无关的实现细节)。

当它检测到这种情况时,它会尝试打破死锁。

我们当前的方法是基本上随机获取线程,唤醒它们,然后再次挂起它们,直到我们检测到断言辅助线程的进度。这……很随意,而且很慢。

为了更快地选择正确的线程,我想确定给定的 Windows 线程当前是否拥有临界区(可能还有其他同步原语)。然后我们可以先尝试这些线程。

那么,有没有办法确定一个 windows 线程当前是否在挂起时持有一个 CriticalSection?

【问题讨论】:

算了。你不应该像记录的那样打电话给SuspendThread。这就是为什么。从外部正确地完成工作。您不能希望通过在自己的进程中挂起任意线程来取得成功。正如你所发现的那样。 不是一个很好的答案,但为什么要避免在断言线程中分配很难呢?我会想象,对于这样的线程来说这是一件很自然的事情吗? @SergeyA 因为我们正在启动一个带有断言响应选项的对话框。在不分配内存的情况下启动对话框很棘手。 用户界面,我明白了。我相信,您可以轻松地将 UI 外包给其他流程,对吧? 您可以使用 MessageBox 显示对话框而不分配内存。它旨在处理内存不足的情况。 【参考方案1】:

我认为没有记录在案的方法可以判断线程是否处于关键部分,如果存在,我认为这不是解决问题的正确方法。

但要回答这个问题,您可以窥视CRITICAL_SECTION 数据结构的内部,并查看拥有它的线程的句柄。这并没有直接回答这个问题,“这个线程是否在任何关键部分内?”但它确实让你回答,“这个线程在 this 关键部分内吗?”至少在CRITICAL_SECTION 的一些关键实现细节发生变化之前。

对于您的实际问题,我会问您的断言引擎提供了什么好处,而在断言失败时附加调试器并不能更好地处理这些好处。调试器是外部的,绕过任何死锁,并且已经知道如何遍历堆栈,因此您不必重新实现。

【讨论】:

以上是关于确定 Windows 线程是不是在关键部分或类似部分?的主要内容,如果未能解决你的问题,请参考以下文章

snprintf() 是不是在内部调用 memset() 或类似的?

给定一个线程 id,如何确定它是不是仍在 Windows 上运行

如何确定 div 是不是滚动到底部?

单元测试引用了关键部分类

关键部分 - 是还是否?

什么是线程中的关键部分