2

I have a problem with the method wait_until on c++11 conditional variables. It looks like the method return std::cv_status::no_timeout even if there are no notifications. The code below shows the problem.

There are comments in the code below illustrating the problem.

Compiler used: gcc 4.9.2 (on arch linux) gcc 4.8.1 (on ubuntu 14.04)

I am greatful for any help i can get to solve this.

Best regars, Mats

#include <iostream>
#include <atomic>
#include <condition_variable>
#include <mutex>
#include <thread>
#include <chrono>


std::mutex m;
std::condition_variable v;

void test_wait_until(int ms)
{
    std::unique_lock<std::mutex> lock(m);

    std::cout << ms << "ms start\n";
    auto expires = std::chrono::system_clock::now() + std::chrono::milliseconds(ms);
    bool run = true;

    do
    {
        // This loop will run at 100% cpu time until
        // the timeout expires.

        auto status = v.wait_until(lock, expires);

        if(status == std::cv_status::timeout){
            std::cout << ms << "ms expired\n";
            run=false;
        }

        if(status == std::cv_status::no_timeout){
            // If the commend below is removed the
            // termial will be filled by the printout.
            // until the timeout expires.

            //std::cout << ms << "ms did not expire\n";
        }
    }while(run);
}


int main()
{
    test_wait_until(20000);
    test_wait_until( 5000);
    test_wait_until(  100);
    test_wait_until(  100);
    test_wait_until(   10);
    test_wait_until(    0);
    test_wait_until(   -10);
    test_wait_until(  -100);
    test_wait_until(  -100);
    test_wait_until( -5000);
    test_wait_until(-20000);
}
WhozCraig
  • 65,258
  • 11
  • 75
  • 141
mlom
  • 373
  • 3
  • 9
  • 1
    I would guess this is due to spurious wakeups. The documentation for `std::cv_status` for `no_timeout` dictates "the condition variable was awakened with notify_all, notify_one, or spuriously" – Sir Digby Chicken Caesar May 09 '15 at 22:26
  • The loop runs as fast as it can (100% cpu). – mlom May 09 '15 at 22:28
  • Also, is this the only thread running? Perhaps this is an underlying cause for abnormal amounts of spurious wakeups. – Sir Digby Chicken Caesar May 09 '15 at 22:30
  • [Can't reproduce on GCC 5.1 with the future expiry times](http://coliru.stacked-crooked.com/a/f3e2bfaa564b6f82), [nor the past ones](http://coliru.stacked-crooked.com/a/409e077aed073a39). – Lightness Races in Orbit May 09 '15 at 22:31
  • Yes there are only one thread in the program. The CPU is normally barely loaded ( < 4% ), but when the program runs and is in the loop the program uses 100% of that CPU core. – mlom May 09 '15 at 22:33
  • If GCC 5.1 runs it ok, it must be a bug in older versions. I have to try that. – mlom May 09 '15 at 22:35
  • Couldn't find anything relevant on Bugzilla. – Lightness Races in Orbit May 09 '15 at 22:43
  • clang 3.6 seems to have no worries either (Apple OSX 10.10.3). Everything looks normal. So at least you have options. – WhozCraig May 10 '15 at 00:17
  • @sird The non-printing version is dealing with spirious wakeups (by looping) reasonably. It taking 100% cpu is a poor QoI. @ mlom: Have you seen this happen in non-toy code? You have a mutex that cannot be shared, a loop that does nothing unless that mutex is shared (and waiting is optional): I cpuld see an optimizer going nuts. What are your build flags (all of them)? I am curious how bad the bug is. – Yakk - Adam Nevraumont May 10 '15 at 07:37
  • 1
    Yes it was in real production code. The code example above is a example of how to reproduce the behavior. The compiler flag -pthread was missing. That means that at least the c++11 thread library starts acting funny at some places. As I understand it the -pthread flag affects how the code is compiled. After adding the -pthread flag both the "toy" code and the production code behaves as it should. 0% cpu wile waiting for the time to expire. – mlom May 10 '15 at 17:40
  • The build flags when the loop takes 100%:  `g++ -std=c++11 t.cpp -o test` – mlom May 10 '15 at 17:44
  • The build flags when the loop takes 0%:  `g++ -std=c++11 -pthread t.cpp -o test` – mlom May 10 '15 at 17:45
  • How did you intend to use condition variables without threading? – Yakk - Adam Nevraumont May 10 '15 at 23:30
  • Ofcourse there are threads in the real code. The code above is reduced to show the behavior with as little code as possible. Anyway the problem is solved. – mlom May 11 '15 at 10:51

2 Answers2

4

You probably need to build your executable with threading support. On Linux with gcc 4.9.2 this would go something like this:

g++ -std=c++11 test.cpp -o test -pthread
lierdakil
  • 548
  • 2
  • 9
-1

Ok the problem was: I / we were using the -lpthread option instead of the -pthread option for gcc.

The strange this is other things works rather well, but this seams to the solution.

Thank you all!

mlom
  • 373
  • 3
  • 9