TFM
TFM

Reputation: 717

Unexpected results with std::thread under Cygwin

I'm not sure whether std::thread is supposed to be working under Cygwin. The only posts I find are years old and deal with compiler errors. So this problem is a bit different.

I am porting an application from Linux to Cygwin. It uses multiple threads with std::thread and works except for one thing: In one place a call to std::thread::detach() throws with Invalid argument although std::thread::joinable() returns true.

I tried to built an example:

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

std::thread* t;
std::mutex m;
std::condition_variable cv;

void func(void)
try
{
    std::cout << "func" << std::endl;
    if (t->joinable())
    {
        std::cout << "t is joinable" << std::endl;
        t->detach();
        delete t;
        std::unique_lock<std::mutex> lck(m);
        cv.notify_all();
    }
}
catch(std::exception& e)
{
    std::cout << "exception in func: " << e.what() << std::endl;
}


int main(void)
{
    try
    {
        std::unique_lock<std::mutex> lck(m);
        t=new std::thread(&func);
        cv.wait(lck);
        std::cout << "func finished" << std::endl;
        cv.wait(lck);
    }
    catch(std::exception& e)
    {
        std::cout << "exception in main: " << e.what() << std::endl;
    }

    return(0);
}

I compile this on Linux with

g++ -std=c++0x -pthread example.cc

using gcc version 4.6.3. It produces

func
t is joinable
func finished

then hangs indefinitely every time, which is expected behaviour due to the second, unmatched call to cv.wait().

On Cygwin I compile with

g++ -std=c++11 -pthread example.cc

using gcc version 4.9.3.

It sometimes shows the above behaviour, sometimes it just shows

func

then exits with 0.

So I cannot reproduce my original error but rather get some more erratic behaviour.

Upvotes: 3

Views: 468

Answers (2)

WhiZTiM
WhiZTiM

Reputation: 21576

First, you are likely a victim of spurious wake up....

An implementation is permitted to wake up a condition variable, so it is your responsibility to ensure that your condition is met ... You can do this by supplying an extra argument to cv.wait()

Please see: http://www.cplusplus.com/reference/condition_variable/condition_variable/wait/

Secondly, getting only "func" as an output with an exited zero(0) worries me. Cause that shouldn't happen at all.

At least "func has finished" should be printed because you flushed the stream : std::endl;

Upvotes: 1

&#214;&#246; Tiib
&#214;&#246; Tiib

Reputation: 10979

Your posted program contains undefined behavior. There two threads (main and func) race to access t (that is ordinary, non-atomic raw pointer).

What happens with programs that contain undefined behavior includes (but is not limited to) nasal demons. So both linux and cygwin seem to work in that sense just the nasal demons happen to be of different kinds.

Upvotes: 1

Related Questions