Windows SuspendThread 没有?(GetThreadContext 失败)

Ira*_*ter 5 windows winapi multithreading suspend

我们有一个 Windows32 应用程序,其中一个线程可以通过执行 SuspendThread/GetThreadContext/ResumeThread 来停止另一个线程以检查其状态 [PC 等]。

if (SuspendThread((HANDLE)hComputeThread[threadId])<0)  // freeze thread
   ThreadOperationFault("SuspendThread","InterruptGranule");
CONTEXT Context, *pContext;
Context.ContextFlags = (CONTEXT_INTEGER | CONTEXT_CONTROL);
if (!GetThreadContext((HANDLE)hComputeThread[threadId],&Context))
   ThreadOperationFault("GetThreadContext","InterruptGranule");
Run Code Online (Sandbox Code Playgroud)

极少数情况下,在多核系统上,GetThreadContext 返回错误代码 5(Windows 系统错误代码“拒绝访问”)。

SuspendThread 文档似乎清楚地表明目标线程已挂起,如果没有返回错误。我们正在检查 SuspendThread 和 ResumeThread 的返回状态;他们从来没有抱怨过。

怎么可能我可以挂起一个线程,但不能访问它的上下文?

这个博客 http://www.dcl.hpi.uni-potsdam.de/research/WRK/2009/01/what-does-suspendthread-really-do/

表明 SuspendThread 在返回时可能已开始暂停另一个线程,但该线程尚未暂停。在这种情况下,我可以看出 GetThreadContext 会有什么问题,但这似乎是定义 SuspendThread 的愚蠢方法。(SuspendThread 的调用如何知道目标线程何时真正挂起?)

编辑:我撒谎了。我说这是针对 Windows 的。

好吧,奇怪的事实是,我在 Windows XP 64 下没有看到这种行为(至少在上周没有,我真的不知道在那之前发生了什么)……但我们一直在测试这个 Windows 应用程序Ubuntu 10.x 上的 Wine。当由于某种原因尝试获取线程状态失败时,GetThreadContextWine 源在第 819 行包含拒绝访问的返回响应。我在猜测,但似乎 Wine GetThreadStatus 认为线程可能无法重复访问。为什么在 SuspendThead 超出我的范围之后这会是真的,但有代码。想法?

EDIT2:我又撒谎了。我说我们只看到了 Wine 上的行为。不......我们现在发现了一个 Vista Ultimate 系统,它似乎会产生同样的错误(同样,很少)。因此,Wine 和 Windows 似乎就一个晦涩的案例达成了一致。似乎仅启用 Sysinternals Process 监控程序会加剧情况并导致问题出现在 Windows XP 64 上;我怀疑是海森虫。(进程监视器甚至不存在于品酒 (:-) 机器或我用于开发的 XP 64 系统上)。

它到底是什么?

EDIT3:2010 年 9 月 15 日。我添加了对错误返回状态的仔细检查,而不会干扰 SuspendThread、ResumeThread 和 GetContext 的代码。自从我这样做以来,我还没有在 Windows 系统上看到任何这种行为的迹象。还没有回到 Wine 实验。

2010 年 11 月:奇怪。似乎如果我在 VisualStudio 2005 下编译它,它会在 Windows Vista 和 7 上失败,但不会在更早的操作系统上失败。如果我在 VisualStudio 2010 下编译,它不会在任何地方失败。有人可能会指责 VisualStudio2005,但我怀疑位置敏感问题,VS 2005 和 VS 2010 中的不同优化器将代码放置在略有不同的位置。

2012 年 11 月:传奇仍在继续。我们在许多 XP 和 Windows 7 机器上看到了这种故障,发生率非常低(每几千次运行一次)。我们的 Suspend 活动应用于主要执行纯计算代码但有时会调用 Windows 的线程。当线程的 PC 在我们的计算代码中时,我不记得看到这个问题。当然,挂掉的时候是看不到线程的PC的,因为GetContext不会给我,所以我不能直接确认问题只发生在执行系统调用的时候。但是,我们所有的系统调用都通过一个点进行引导,到目前为止,证据表明当我们挂起时,这个点就被执行了。因此,间接证据表明线程上的 GetContext 仅在该线程正在执行系统调用时才会失败。我没有

D.S*_*ley 3

围绕挂起拥有CriticalSection. 我现在找不到很好的参考资料,但是Raymond Chen 的博客上有一次提到过它Chris Brumme 的博客上也有一次提到过。基本上,如果您不幸SuspendThread在线程访问操作系统锁(例如,堆锁、DllMain锁等)时调用,那么可能会发生非常奇怪的事情。我认为您很少遇到这种情况。

GetThreadContext在处理器产生类似结果后重试调用是否有效Sleep(0)