Windows 10特定的调用LeaveCriticalSection崩溃 [英] Windows 10 specific crash on call LeaveCriticalSection

查看:674
本文介绍了Windows 10特定的调用LeaveCriticalSection崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Windows 10上遇到线程同步和关键部分的问题.

I stucked into a problem with threads syncronization and critical sections on Windows 10.

在这种情况下,应用程序将崩溃:

Application will crash in this case:

  • 应用程序有两个线程.
  • 线程1使用对象m_CS调用EnterCriticalSection
  • 然后线程2尝试输入相同的关键部分
  • 线程1使用TerminateThread终止线程2
  • 线程1调用LeaveCriticalSection

在我能够测试的Windows早期版本(7、8、8.1)中,此功能正常运行.线程2终止,线程1毫无例外地离开了关键部分.

In previous Windows versions which I was able to test (7, 8, 8.1) this works properly. Thread 2 terminates, and Thread 1 leaves the critical section without exception.

在Windows 10上,当线程1离开关键部分时,应用程序将因访问冲突而崩溃.只有在等待EnterCriticalThread时另一个线程被终止时,这种情况才会发生.

On Windows 10, when Thread 1 leaves the critical section, application crashes with Access Violation. It only happens when another thread was terminated while waiting on EnterCriticalThread.

查看堆栈跟踪,它看起来像这样(顶部的最后一帧):

Looking at the stack trace it looks this (latest frame at the top):

RtlpWakeByAddress
RtlpUnWaitCriticalSection
RtlLeaveCriticalSection

我花了很多时间来调试此问题.在我的情况下,调用LeaveCriticalSection时,m_CS完全可以.我调试并花了一些时间来分析ntdll.dll函数的反汇编代码.似乎对象在执行RtlpUnWaitCriticalSection的过程中在某处损坏,然后在发生崩溃时传递给RtlpWakeByAddress.基本上ntdll.dll能够修改CRITICAL_SECTION对象的属性,例如RtlLeaveCriticalSection中的锁计数.

I spent so much time on debugging this issue. In my case m_CS is totally fine when LeaveCriticalSection was called. I debugged and spent some time to analyze disassembled code of ntdll.dll functions. Seems like object corrupts somewhere during execution of RtlpUnWaitCriticalSection and then passed to RtlpWakeByAddress when crash occurs. Basicly ntdll.dll was able to modify CRITICAL_SECTION object's properties such as lock count in RtlLeaveCriticalSection.

在网络上,我没有找到任何答案,也没有声明Windows 10中发生了什么变化.在上个月,只有Reddit线程和Mozilla Firefox的〜1800崩溃报告具有相同的调用堆栈.我与reddit上的帖子作者联系,到目前为止,他无法解决此问题.

From the web I didn't find any answer on this or statement what changed in Windows 10. Only thread on reddit and ~1800 crash reports for Mozilla Firefox with same call stack in the last month. I contacted with author of post on reddit and he was not able to fix this thus far.

因此有人处理过此问题,可能对此有解决方案或建议吗?现在,作为解决方案,我只想重新考虑WinAPI TerminateThread的用法,并尝试尽可能避免使用它.另一种方法可能是进行代码重构并考虑应用程序的体系结构.

So anybody dealed with this issue and may be have a fix for it or advices? As a solution right now I only see to rethink usage of WinAPI TerminateThread and try to avoid it as much as possible. Another way probably to do a code refactoring and think on application's architecture.

任何回应表示赞赏. 预先感谢

Any response appreciated. Thanks in advance

推荐答案

线程1使用TerminateThread终止线程2

Thread 1 terminates Thread 2 using TerminateThread

不要那样做.看起来它可以在其他Windows版本上使用,但是您无法确定自己正在发生什么副作用并对其隐藏.

Don't do that. It may look like it works on other windows versions, but there's no way for you to know for sure what side-effects are occurring and hiding from you.

来自 https://msdn.microsoft.com/zh-CN/library/windows/desktop/ms686717(v=vs.85).aspx

TerminateThread是一个危险的函数,仅应在 最极端的情况.仅在以下情况下才应调用TerminateThread 确切知道目标线程在做什么,然后您控制所有 目标线程当时可能正在运行的代码 终止.例如,TerminateThread可能会导致 存在以下问题:

TerminateThread is a dangerous function that should only be used in the most extreme cases. You should call TerminateThread only if you know exactly what the target thread is doing, and you control all of the code that the target thread could possibly be running at the time of the termination. For example, TerminateThread can result in the following problems:

  • 如果目标线程拥有一个关键部分,则该关键部分将不会被释放.
  • 如果目标线程正在从堆中分配内存,则不会释放堆锁.
  • 如果目标线程在终止时正在执行某些kernel32调用,则该线程进程的kernel32状态可能为 不一致.
  • 如果目标线程正在操纵共享DLL的全局状态,则DLL的状态可能会被破坏,从而影响DLL的其他用户. DLL.
  • If the target thread owns a critical section, the critical section will not be released.
  • If the target thread is allocating memory from the heap, the heap lock will not be released.
  • If the target thread is executing certain kernel32 calls when it is terminated, the kernel32 state for the thread's process could be inconsistent.
  • If the target thread is manipulating the global state of a shared DLL, the state of the DLL could be destroyed, affecting other users of the DLL.

您应该做的是与线程2通信,并让线程2正确,安全地关闭自身.

What you should do is communicate with thread 2 and let thread 2 shut itself down correctly and safely.

这篇关于Windows 10特定的调用LeaveCriticalSection崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆