当前位置:   article > 正文

Win7下静态变量析构导致进程卡死无法退出问题解决_win7 死线程

win7 死线程

项目中在用户机器Win7系统上好几次出现进程卡死,无法退出,在用户机器上抓取了dump,发现是在DllMain函数中执行了静态变量的析构,这个静态变量析构的时候会使用std::condition_variable 类型的成员变量通知其他线程退出。同时本地在win10机器上并不会出现。

最开始一直没查到原因,解决方法是在main函数退出之前就把静态变量反初始化函数执行,这样在DllMain中就只是一个空的析构函数,不会导致卡死了。

卡死dump截图:

当时我给的建议是,尽量不要在DllMain中执行很多同步逻辑,因为官方的最佳实践文档中给了出的建议也是这样:

https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-best-practices

第三条很明确的说了,不要和其他线程做同步的事情。

(备注:第一条曾经也遇到过这类死锁的dump,调用com组件的时候有时候会加载动态库,从而导致死锁。关键字:Loader Lock) 

一年之后又遇到了一个无法退出的case,我给用户远程并抓取了dump,发现还是类似的问题,只不过代码是在另外一个地方。

上次是我同事发现的这个问题,想办法绕过去了,这次我想弄明白原因,在网上查了一些资料,google查找的关键字:ZwReleaseKeyedEvent deadlock,因为堆栈最后一个函数是这个。

发现了很有价值的两篇文章:

第一篇:

https://stackoverflow.com/questions/60452341/stdconditional-variable-notify-problem-on-windows-7-called-from-destructor-oz​​​​​​​z​​​​​​​f

这篇文章这个人也遇到了,代码和我们的代码几乎一样:

  1. class SomeObject
  2. {
  3. public:
  4. ~SomeObject()
  5. {
  6. StopThreadAndWait();
  7. }
  8. void StopThreadAndWait()
  9. {
  10. /* some logic */
  11. m_stop = true;
  12. m_procesTasks.notify_one(); // <- the problem is here
  13. if (m_thread.joinable())
  14. m_thread.join();
  15. }
  16. private:
  17. ...
  18. bool m_stop;
  19. std::mutex m_workQueueSync;
  20. std::thread m_thread;
  21. std::condition_variable m_procesTasks;
  22. };

第二篇:

https://bugzilla.mozilla.org/show_bug.cgi?id=970063 

也就是说mozilla也遇到过这个问题,并且还给出了问题的答案,答案之一就是安装补丁,因为这个是windows系统的bug:

 

 补丁链接:

A process that is being terminated stops responding in Windows 7 or in Windows Server 2008 R2 - Microsoft Support

上面说明了只在win7 和 Windows Server 2008 R2 系统上会出现此问题。

到此,整个问题已经查明原因了。

但是,用户那里环境我们几乎是不能改变的,比如给用户安装这个补丁似乎成本很大。所以我们 就修改我们自己的代码,不要在DllMain中因为析构静态变量,执行了 std::condition_variable::notify_one(all)之类的函数,放到main函数退出之前执行即可。

第一篇文章中使用boost库中的condition_variable类也可以解决。同时我也把我发现的这个问题写在了这篇文章的评论中了。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/247215
推荐阅读
  

闽ICP备14008679号