Reputation: 26346
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
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