3

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.

TFM
  • 717
  • 6
  • 21
  • Your second `cv.wait()` call is likely to block forever - there's nothing to notify `cv` again. – Alan Stokes Nov 14 '15 at 11:15
  • Not just likely... that would be the expected behaviour. I added the second call to `cv.wait()` to underline that Cygwin in some cases ignores the `cv.wait()` alltogether. Under Linux it always blocks forever which is expected, under Cygwin it sometimes exits. – TFM Nov 14 '15 at 14:29
  • Well, you said it hangs indefinitely without mentioning that you considered that a success. – Alan Stokes Nov 14 '15 at 14:31
  • Yes, I should mention that. – TFM Nov 14 '15 at 14:48

2 Answers2

1

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.

Öö Tiib
  • 10,809
  • 25
  • 44
  • Yes, that is the problem with the above example. Although I'm still not satisfied because I cannot see how this results in skipping over the `cv.wait()` calls. – TFM Nov 14 '15 at 14:50
1

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;

WhiZTiM
  • 21,207
  • 4
  • 43
  • 68