I wrote a simple test prog which contains two data races. But tsan only reports the first one what ever I try to modify.
Is tsan always only reporting a single bug? Maybe tsan can't see some bugs because hidden by others? Any relation to my prog?
My prog: ( it did not do any useful and it has data races by intention! )
#include <thread>
#include <mutex>
#include <atomic>
#include <unistd.h>
std::atomic<bool> stop{false};
std::mutex main_t1_mutex;
std::mutex t1_t2_mutex; // fully useless by intention
// global vars accessed by main and threads
int i1;
int i2;
void func_t1(int* retval)
{
int internal = 0;
//while( !stop )
for ( unsigned int tt = 0; tt < 1000; tt++ )
{
//main_t1_mutex.lock();
t1_t2_mutex.lock();
internal+=i1;
t1_t2_mutex.unlock();
//main_t1_mutex.unlock();
usleep(1*100);
}
*retval=internal;
}
void func_t2(int* retval)
{
int internal = 0;
//while( !stop )
for ( unsigned int tt = 0; tt < 1000; tt++ )
{
// this mutex will never protect against main thread. Intended for testing valgrind/tsan
t1_t2_mutex.lock();
internal+=i2;
t1_t2_mutex.unlock();
usleep(1*100);
}
*retval = internal;
}
int main()
{
std::cout << "Hallo" << std::endl;
int retval1;
int retval2;
std::thread t1( func_t1, &retval1 );
std::thread t2( func_t2, &retval2 );
for ( unsigned int i = 0; i < 10; i++ )
{
usleep(1*1000);
main_t1_mutex.lock();
i1 = i;
i2 = i;
main_t1_mutex.unlock();
std::cout << "step " << i << std::endl;
}
//stop=true;
t1.join();
t2.join();
std::cout << "Value 1: " << retval1 << std::endl;
std::cout << "Value 2: " << retval2 << std::endl;
}
i1
in main, tsan reports the concurrent access ofi2
.i1
is removed from main(), the second bug is reported.