0

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;
}




6
  • After you fix the first race condition problem that tsan discovered, does tsan discover the second race condition problem?
    – Eljay
    Commented Jul 5 at 12:35
  • Could it be that the compiler simply optimizes away some of the code that is either useless or contains UB? Commented Jul 5 at 12:44
  • 1
    @Eljay: Yes, if I simply remove the access of i1 in main, tsan reports the concurrent access of i2.
    – Klaus
    Commented Jul 5 at 13:09
  • @JesperJuhl: Do you see UB? I am in hope that not everything could be optimized away, because the result is used to print it out. And as also remarked, if access to i1 is removed from main(), the second bug is reported.
    – Klaus
    Commented Jul 5 at 13:11
  • 1
    @Klaus A race condition is UB. Commented Jul 5 at 13:46

0

Browse other questions tagged or ask your own question.