Summary: | drd reports false positive for concurrent __atomic_base access | ||
---|---|---|---|
Product: | [Developer tools] valgrind | Reporter: | ewirch <wirch.eduard> |
Component: | drd | Assignee: | Bart Van Assche <bart.vanassche+kde> |
Status: | RESOLVED NOT A BUG | ||
Severity: | normal | ||
Priority: | NOR | ||
Version: | 3.9.0 | ||
Target Milestone: | --- | ||
Platform: | Compiled Sources | ||
OS: | Linux | ||
Latest Commit: | Version Fixed In: | ||
Sentry Crash Report: |
Description
ewirch
2013-12-06 15:37:17 UTC
Forgot to mention: address is onto stack, valgrind executed with --check-stack-var=yes Similar bug reported for helgrind: 327881 It is not possible for a run-time analysis tool like DRD to recognize sig_atomic_t variables at runtime. My recommendation is either to use a data type that can be recognized by DRD (std::atomic ?) or to use DRD_IGNORE_VAR(). Thanks for the info Bart. But I am using std::atomic: ==2561== at 0x421E3B: std::__atomic_base<bool>::load(std::memory_order) const (atomic_base.h:496) ==2561== by 0x421598: std::atomic_bool::operator bool() const (atomic:77) If you can provide a test program that allows to reproduce the above output I will look further into this issue. Sure: #include <pthread.h> #include <stdlib.h> #include <unistd.h> #include <stdio.h> #include <string> #include <atomic> using namespace std; class Thread { public: Thread() { } virtual ~Thread() { } void run() { int err; err = pthread_create(&pThread_, NULL, &Thread::invokeRun, (void*)this); if (err != 0) { throw string("Thread::run(): failed to create a thread."); } } void join() { void *threadRetValue; int err = pthread_join(pThread_, &threadRetValue); if (err != 0) { throw string("Thread::join(): failed to join."); } } virtual void threadWork() = 0; private: static void *invokeRun(void *instance); pthread_t pThread_; }; void *Thread::invokeRun(void *instance) { reinterpret_cast<Thread*>(instance)->threadWork(); return NULL; } class LockDoesLock_Thread1: public Thread { public: atomic<bool> lockAcquired_; atomic<bool> tryLocked_; atomic<bool> unlocked_; atomic<bool> tryLockSuccess1_; atomic<bool> tryLockSuccess2_; pthread_mutex_t &mutex_; LockDoesLock_Thread1(pthread_mutex_t &pLock) : mutex_(pLock) { lockAcquired_ = false; tryLocked_ = false; unlocked_ = false; tryLockSuccess1_ = false; tryLockSuccess2_ = false; } void threadWork() { pthread_mutex_lock(&mutex_); lockAcquired_ = true; while (!tryLocked_) { }; pthread_mutex_unlock(&mutex_); unlocked_ = true; } }; class AutoLockDoesLock_Thread1: public LockDoesLock_Thread1 { public: AutoLockDoesLock_Thread1(pthread_mutex_t &pLock) : LockDoesLock_Thread1(pLock) { } void threadWork() { doAutoLock(); unlocked_ = true; } void doAutoLock() { pthread_mutex_lock(&mutex_); lockAcquired_ = true; while (!tryLocked_) { }; pthread_mutex_unlock(&mutex_); } }; class LockDoesLock_Thread2: public Thread { public: LockDoesLock_Thread2(LockDoesLock_Thread1 &buddy) : buddy_(buddy) { } void threadWork() { while (!buddy_.lockAcquired_) { } buddy_.tryLockSuccess1_ = (pthread_mutex_trylock(&buddy_.mutex_) == 0); buddy_.tryLocked_ = true; while (!buddy_.unlocked_) { } buddy_.tryLockSuccess2_ = (pthread_mutex_trylock(&buddy_.mutex_) == 0); if (buddy_.tryLockSuccess2_) { pthread_mutex_unlock(&buddy_.mutex_); } } private: LockDoesLock_Thread1 &buddy_; }; int main(int argc, char** argv) { pthread_mutex_t mutex; pthread_mutex_init(&mutex, NULL); AutoLockDoesLock_Thread1 t1(mutex); LockDoesLock_Thread2 t2(t1); t1.run(); t2.run(); t1.join(); t2.join(); if (t1.tryLockSuccess1_ != false) printf("Test fail 1\n"); if (t1.tryLockSuccess2_ != true) printf("Test fail 2\n"); return true; } Compile with: g++ -std=c++11 atomictest.cpp -o atomictest -lpthread Test with: valgrind --tool=drd --check-stack-var=yes ./atomictest What I see in libstdc++ is the following: * atomic<bool> is represented by a single byte. * atomic<bool>::store() uses __atomic_store_n(), and for bool __atomic_store_n() is a compiler-built-in that uses a regular single-byte store. Sorry but it's not clear to me how DRD or any other Valgrind tool could discern such store operations from regular store operations. Please use DRD_IGNORE_VAR() or equivalent to suppress race reports on atomic<bool> variables. |