首页 > 解决方案 > 从静态变量的析构函数调用 Windows 7 上的 std::conditional_variable notify() 问题

问题描述

当从静态变量的析构函数调用 Windows 7 时,std::conditional_variable notify()我遇到了问题。notify_all()

对象看起来像这样(逻辑被简化):

class SomeObject
{
public:
    ~SomeObject()
    {
        StopThreadAndWait();
    }
    
    void StopThreadAndWait()
    {
            /* some logic  */
            m_stop = true;
            m_procesTasks.notify_one(); // <- the problem is here
            
            if (m_thread.joinable())
                m_thread.join();
    }
    
private:
    ...
    bool        m_stop;
    std::mutex  m_workQueueSync;
    
    std::thread m_thread;
    std::condition_variable m_procesTasks;
};

SomeObject -- 是一个静态变量。

当我们打电话时~SomeObject()-m_thread已经停止了。但在 Windows 7 上,我们遇到了麻烦。

在调用堆栈的顶部:(这是应用程序的唯一线程)

ntdll.dll!ZwReleaseKeyedEvent()
ntdll.dll!RtlpWakeConditionVariable()
ntdll.dll!RtlWakeConditionVariable()
MSVCP140D.dll!__crtWakeAllConditionVariable(_RTL_CONDITION_VARIABLE * pCond)
MSVCP140D.dll!Concurrency::details::stl_condition_variable_win7::notify_one()
....
ntdll.dll!RtlExitUserProcess()
...

我知道,静态对象的析构函数中的同步 - 不好的做法(它是遗留代码)有很多方法可以修复它。

但是,这似乎是在 Win 7 的 140 运行时中实现 STL 的错误(在 Win 10 上一切正常)。如果是的话,我在互联网上找不到任何关于它的信息

更新:

在另一个项目中遇到了这个问题,所以对于任何可能遇到这个问题的人:

问题: 似乎在 Win7 上执行条件变量时出现了一些问题(由于Concurrency::details::stl_condition_variable_win7::notify_one()

出现,当有一个条件变量时,我想等待该变量的线程由于某种原因而终止(在我的情况下 - 由于进程关闭)

在这种情况下std::conditional_variable::notify() 会导致挂起。

可能的解决方案

最好的解决方案 - 只是为了修复架构,因为静态对象中的线程 - 不是最好的方法。

另一种选择 - 使用 boost 而不是 STL

标签: c++multithreadingsynchronizationcondition-variable

解决方案


我遇到了同样的问题,只在 windows 7 上。相同的代码在 Windows 10 上运行。当我们到达 notify_all(我的案例)或 notify_one(此处)时,似乎 STL condition_variable 的基础架构已经以某种方式被拆除。

在我的情况下,有 8 个线程在等待,但是当程序挂起时它们都死了,所以 notify_all 完成了它的工作,但从未返回。在我的调用堆栈中有一个包含 win7 的函数名称,因此很可能在 win7 和 win 10 中运行不同的代码:

    ntdll.dll!ZwReleaseKeyedEvent()    Unknown
    ntdll.dll!string "Enabling heap debug options\n"() Unknown
    msvcp140d.dll!__crtWakeAllConditionVariable(_RTL_CONDITION_VARIABLE * pCond) Line 450   C++
    msvcp140d.dll!Concurrency::details::stl_condition_variable_win7::notify_all() Line 188  C++
    msvcp140d.dll!do_signal(_Cnd_internal_imp_t * cond, int all) Line 80    C++
    msvcp140d.dll!_Cnd_broadcast(_Cnd_internal_imp_t * cond) Line 101   C++
    cvie64.dll!std::condition_variable::notify_all() Line 596   C++
    cvie64.dll!ctpl::thread_pool::interrupt(bool kill) Line 166 C++

推荐阅读