【问题标题】:Terminate a waiting thread终止等待线程
【发布时间】:2020-04-21 04:30:29
【问题描述】:

我有一个 win32 线程,正在等待带有“WaitForSingleObject”函数的互斥锁。 终止线程(使用 TerminateThread)是否安全? 在微软文档中,他们说 TerminateThread 很危险,但在这种情况下吗? 谢谢

【问题讨论】:

  • 更危险的是,互斥状态没有得到正确恢复。接下来程序将因 WAIT_ABANDONED 而失败。互斥体可以报告这种不可恢复的同步状态损坏非常有用。
  • 这总是不安全的调用TerminateThread,因为线程已经可以停止等待并开始做另一项工作。如果您在它例如在关键部分(例如分配或从堆中释放)时终止它 - 在此之后所有进程都可以冻结。调用 TerminateThread 总是不好的解决方案,使用 WaitForSingleObjectEx 并发送 apc 以获得线程或更好 - 使用 ZwWaitForSingleObject 在这种情况下您可以向线程发送警报
  • 您好,您解决了这个问题吗?你有答案吗?请随意标记它,或添加您的答案然后标记自己以帮助遇到相同问题的人。

标签: winapi


【解决方案1】:

致电TerminateThread 总是很糟糕而且永远不会安全。当您调用TerminateThread 时,线程已经可以完成等待并开始执行其他操作。例如,可能会从堆中分配或释放内存,因此在临界区中。如果此时终止线程 - 关键部分永远不会空闲,并且所有进程在下一次堆调用时逐个线程挂起。在任何情况下,一些线程资源不会是空闲的,直到进程退出。

然而从来不需要终止线程。可能找到干净的解决方案。您可以使用WaitForSingleObjectEx 等待处于警报状态,如果您想打破这种等待,您需要调用QueueUserAPC(带有一些虚拟回调)而不是TerminateThread

VOID NTAPI DummyApcFunc(_In_ ULONG_PTR /*Parameter*/){
}
//----------------
    switch (WaitForSingleObjectEx(hMutex, INFINITE, TRUE))
    {
    case WAIT_OBJECT_0:
    case WAIT_ABANDONED_0:
        DbgPrint("mutex acquired\n");
        break;
    case STATUS_USER_APC:
        DbgPrint("stop wait for mutex\n");
        break;
    case WAIT_FAILED:
        GetLastError();
        break;
    default:
        __debugbreak();
    }
//----------------
QueueUserAPC(DummyApcFunc, hThread, 0);

甚至更好 - 使用 ZwWaitForSingleObject - 在这种情况下,您可以通过警报中断线程等待,而不需要虚拟 apc

    switch (ZwWaitForSingleObject(hMutex, TRUE, 0))
    {
    case WAIT_OBJECT_0:
    case WAIT_ABANDONED_0:
        DbgPrint("mutex acquired\n");
        break;
    case STATUS_USER_APC:
    case STATUS_ALERTED:
        DbgPrint("stop wait for mutex\n");
        break;
    default:
        __debugbreak();
    }
//------------------------------
ZwAlertThread(hThread);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多