Important: Please read the Qt Code of Conduct -

QWaitCondition: how to avoid lost wakeup?

  • Quite recently, we have detected a QWaitCondition in our code that suffers from
    the lost wakeup problem. For more information on this problem,
    please refer to that
    describes it for C++11's std::condition_variable (I believe the
    description there is also valid for condition variables of type QWaitCondition).

    Basically, what we do is the following: we first send a message to a server,
    and then wait for a reply using something like the following:

    bool SomeController::mfWaitForAnswer(int timeoutInMilliSeconds)
        bool responseReceivedWithinTimeout = true;
        if (!mvResponseReceived)
            responseReceivedWithinTimeout = mvWait.wait(&mvResponseReceivedMutex, 
        return responseReceivedWithinTimeout;

    where mvWait is the problematic QWaitCondition. Elsewhere, we have the wakeup
    code that gets executed when a message from the server arrives:

    void SomeController::mpMessageReceived(const QString& message)
        mvMessage = message;
        mvResponseReceived = true;

    The problem is that if the server is very fast to reply, then the call to
    mvWait.wakeAll() occurs between the sending of the message to the server and
    the mvWait.wait() call. Thus, the QWaitCondition is not waiting yet and we have
    a lost wakeup.

    Now, on it is
    explained that for std::condition_variable::wait, one can add a Predicate to
    overcome this problem. See also However, I
    don't see such a facility for QWaitCondition.

    I'm quite sure we are not the only ones suffering from the lost wakeup issue
    with a QWaitCondition. Can I get some advice on what is the typical way to
    address this? (Note that we are still using Qt 4.8.7 and time and priorities
    are holding us from upgrading yet...)

  • Problem solved. My original diagnose was incorrect: we did not suffer from the Lost Wakeup problem. The real problem was that mpMessageReceived was never called. The reason why it never got called was that we had a non-working signal-slot connection. And the reason for that non-working signal-slot connection was that there was no event loop running (where we thought there was).

Log in to reply