Skip to content

Commit

Permalink
Fix thread-sanitizer warning about a data race
Browse files Browse the repository at this point in the history
Not 100% sure if this is a bug in tsan, but turning expected into an
atomic variable will avoid the warnings.

Change-Id: I6d6a5d58f90258d201ae3880473228638de0a215
Reviewed-by: Thiago Macieira <[email protected]>
Reviewed-by: Andrei Golubev <[email protected]>
  • Loading branch information
laknoll committed May 12, 2021
1 parent 224fccd commit a8a38f7
Showing 1 changed file with 10 additions and 9 deletions.
19 changes: 10 additions & 9 deletions src/testlib/qtestcase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1016,7 +1016,7 @@ class WatchDog : public QThread
};

bool waitFor(std::unique_lock<QtPrivate::mutex> &m, Expectation e) {
auto expectationChanged = [this, e] { return expecting != e; };
auto expectationChanged = [this, e] { return expecting.load(std::memory_order_relaxed) != e; };
switch (e) {
case TestFunctionEnd:
return waitCondition.wait_for(m, defaultTimeout(), expectationChanged);
Expand All @@ -1035,44 +1035,45 @@ class WatchDog : public QThread
{
setObjectName(QLatin1String("QtTest Watchdog"));
auto locker = qt_unique_lock(mutex);
expecting = ThreadStart;
expecting.store(ThreadStart, std::memory_order_relaxed);
start();
waitFor(locker, ThreadStart);
}
~WatchDog() {
{
const auto locker = qt_scoped_lock(mutex);
expecting = ThreadEnd;
expecting.store(ThreadEnd, std::memory_order_relaxed);
waitCondition.notify_all();
}
wait();
}

void beginTest() {
const auto locker = qt_scoped_lock(mutex);
expecting = TestFunctionEnd;
expecting.store(TestFunctionEnd, std::memory_order_relaxed);
waitCondition.notify_all();
}

void testFinished() {
const auto locker = qt_scoped_lock(mutex);
expecting = TestFunctionStart;
expecting.store(TestFunctionStart, std::memory_order_relaxed);
waitCondition.notify_all();
}

void run() override {
auto locker = qt_unique_lock(mutex);
expecting = TestFunctionStart;
expecting.store(TestFunctionStart, std::memory_order_release);
waitCondition.notify_all();
while (true) {
switch (expecting) {
Expectation e = expecting.load(std::memory_order_acquire);
switch (e) {
case ThreadEnd:
return;
case ThreadStart:
Q_UNREACHABLE();
case TestFunctionStart:
case TestFunctionEnd:
if (Q_UNLIKELY(!waitFor(locker, expecting))) {
if (Q_UNLIKELY(!waitFor(locker, e))) {
stackTrace();
qFatal("Test function timed out");
}
Expand All @@ -1083,7 +1084,7 @@ class WatchDog : public QThread
private:
QtPrivate::mutex mutex;
QtPrivate::condition_variable waitCondition;
Expectation expecting;
std::atomic<Expectation> expecting;
};

#else // !QT_CONFIG(thread)
Expand Down

0 comments on commit a8a38f7

Please sign in to comment.