The Quantum Physicist
The Quantum Physicist

Reputation: 26346

Clang ThreadSanitizer: unlock of an unlocked mutex, and an atomic is creating a data-race

I'm thread-analyzing using ThreadSanitizer, and I'm getting a warning that's very, very confusing to my understanding on how mutexes work. I'm using gcc 6.3 on Debian Stretch.

In a class, at one thread, I have:

auto MyPtr = std::make_shared<MyClass>(...);

At another place that's called by another thread, I have:

if(MyPtr.get()) {...}

ThreadSanitizer warned me about a race condition, which is great. So I fixed this by the following:

std::unique_lock<decltype(MyMutex)> lg(MyMutex); //MyMutex is std::mutex
auto MyPtr = std::make_shared<...>(...);
lg.unlock();

And the other spot:

std::unique_lock<decltype(MyMutex)> lg(MyMutex);
if(MyPtr.get()) {...}
// mutex unlocks at the end of the function, which is like after another if-condition.

Now the data race is gone, and ThreadSanitizer says that the Mutex is being unlocked "twice"...

WARNING: ThreadSanitizer: unlock of an unlocked mutex (or by a wrong thread)

and it's pointing to the unlock() call + the end of the other function.

How could a mutex be unlocked twice? Could someone explain?

Now Since this gave me this headache, I decided to do this instead:

std::shared_ptr<MyClass> MyPtr; //in the class definition
std::atomic_store(&MyPtr, std::make_shared<MyClass>(...));

And now I get a data-race complaint:

WARNING: ThreadSanitizer: data race

So am I using ThreadSanitizer wrong? Could someone explain what's going on here?

Upvotes: 2

Views: 1149

Answers (1)

The Quantum Physicist
The Quantum Physicist

Reputation: 26346

I never figured out the mutex problem, but I was able to get rid of the data race with atomics by making the other load atomic:

if(std::atomic_load(&MyPtr).get()) {...}

Upvotes: 1

Related Questions