0

For some reason, my project is always crashing when I call std::condition_variable::wait_for(). Unfortunately, this project's crash handler goes out of its way to be as unhelpful as possible, but it seems pretty clear from log messages that wait_for() is crashing, but my try-catch block isn't working, so I have no idea what the problem is.

The worker thread is supposed to do some work, then sleep for 60 seconds and work again. Obviously, not ad infinitum, so that's why we have the conditional_variable to wakeup the worker thread early and exit the loop. This is the code in the worker thread:

static void spawned(CmdHandler *pThis) {
    std::unique_lock<std::mutex> lk(pThis->m_mxQuit);
    while (!pThis->m_bQuit) {
        lk.unlock();
        pThis->worker.work();
        lk.lock();
        LOG_DEBUG << L"gonna give him wait_for() and I own the lock: " << (lk.owns_lock() ? L"true" : L"FALSE") << L"!";
        try {
            auto ret = pThis->m_cvQuit.wait_for(lk, std::chrono::seconds(60), [&] { return pThis->m_bQuit.load(); });
            LOG_DEBUG << L"and ret is (" << (ret ? L"true" : L"false") << L") and pThis->m_bQuit (" << (pThis->m_bQuit ? L"true" : L"false") << L")";
        }
        catch (std::exception& e) {
            LOG_DEBUG << L"ugh: " << toWide(e.what());
        }
        catch (...) {
            LOG_DEBUG << L"Unknown";
        }
    }
}

std::future<void> m_threadMeta;
std::condition_variable m_cvQuit;
std::atomic_bool m_bQuit;
std::mutex m_mxQuit;

The call to spawned() is very simple:

m_threadMeta = std::async(std::launch::async, spawned, this);

It doesn't lock m_mxQuit or affect m_cvQuit, and this (which is a CmdHandler) definitely lasts for the thread's duration--the dtor is not called.

I'd show you the main thread code which sets m_bQuit, but I guess there's no point, because it never gets called: debug log messages make that clear.

That first debug message before the try writes to the log, and it indicates that the thread owns the lock, but none of the other messages get through, so it's pretty clear that what_for() crashes, but I can't see anything wrong with call, and I'm not getting any log feedback about what's wrong.

I'm doing this in VS2015.

Edit: As per recommendations, I've also tried this, but they made no difference--it still crashes on wait_for():

static void spawned(CmdHandler *pThis) {
    bool bQuit;
    {
        std::lock_guard<std::mutex> lock(pThis->m_mxQuit);
        bQuit = pThis->m_bQuit;
    }
    while (!bQuit) {
        pThis->worker.work();
        bQuit = pThis->waitForQuit();
    }
}

bool waitForQuit() {
    std::unique_lock<std::mutex> lk(m_mxQuit);      //wait_for() insists on unique_lock
    LOG_DEBUG << L"gonna give him wait_for() and I own the lock: " << (lk.owns_lock() ? L"true" : L"FALSE") << L"!";
    m_cvQuit.wait_for(lk, std::chrono::seconds(60), [&] { return m_bQuit.load(); });
    LOG_DEBUG << L"back and now quit is: " << (m_bQuit ? L"true" : L"FALSE") << L"!";
    return m_bQuit;
}
12
  • Check pThis is still valid and has not been deleted on another thread; or even by pThis->worker.work(); Commented Aug 7, 2024 at 21:50
  • @RichardCritten I think the most reliable way to do that would be to show this line: std::async(std::launch::async, spawned, this);. It's the only one that calls spawned(). Commented Aug 7, 2024 at 22:01
  • @Opux That doesn't tell anything about the lifetime of this/pThis. Is the thread launching std::async waiting to destroy this until after .wait() or .get() on the std::future returned by std::async? Commented Aug 7, 2024 at 22:19
  • 1
    This probably isn’t the problem, but volatile (as in volatile bool m_bQuit;) has nothing to do with thread synchronization. Use std::atomic<bool> instead. Commented Aug 8, 2024 at 1:02
  • 1
    @Opux your lambda should then return pThis->m_bQuit.load() ... because atomics are not copyable. Commented Aug 8, 2024 at 7:20

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.