std::condition_variable only works while debugging?

梦想与她 提交于 2019-12-11 10:51:18

问题


I wrote a project in C++14, compiled with Intel's icpc on Fedora 26 (gcc 7 dependency). Everything was good and working, until I moved my project onto Centos 7, and began experiencing very mysterious behavior.

On Centos (scl enable devtoolset-7 bash), source code compiles and links without error, but the project only works while debugging with GDB. Without debugging, the condition variable's notification to wake up a sleeping thread don't function.

Multiple worker threads go to sleep, but notification doesn't work, and they don't wake up. But running with GDB, everything works.

I disabled all optimizations. I tried linking libstdc++ and libgcc statically, but nothing worked. I tried a small test program, and the condition_variable worked fine. I also tested Fedora 27, which fixed the problem.

Here is an example:

    // worker thread
    // term and cv passed in with std::ref()
    std::atomic<bool> &_terminate = term;
    std::condition_variable &_dataConditionVar = cv;
    std::mutex acctMutex;

    while (!_terminate.load(std::memory_order_relaxed)) {
        // do stuff here ....

        // wait for notification
        std::unique_lock<std::mutex> acctLock(acctMutex);
        _dataConditionVar.wait(acctLock);   // Thread never wakes up <<
    }

Works on Fedora 26/27 but doesn't on Centos 7. Anyone have any advice on how to proceed?


回答1:


If _terminate is set after _terminate.load(std::memory_order_relaxed) but before std::unique_lock<std::mutex> acctLock(acctMutex);, _dataConditionVar.wait(acctLock) may block forever.

You do not want to use std::atomic with std::mutex and std::condition_variable because such usage often leads to exactly this race condition. Normally, you use either std::atomic or std::mutex/std::condition_variable.

The correct usage is to make _terminate plain bool and access it only when the mutex is held:

bool _terminate = false;
std::condition_variable _dataConditionVar;
std::mutex acctMutex;

// Set _terminate example.
{
    std::unique_lock<std::mutex> acctLock(acctMutex);
    _terminate = true;
    _dataConditionVar.notify_one();
}

// Wait for _terminate to be set example.
{
    std::unique_lock<std::mutex> acctLock(acctMutex);
    while(!_terminate)
        _dataConditionVar.wait(acctLock);
}


来源:https://stackoverflow.com/questions/50629479/stdcondition-variable-only-works-while-debugging

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!