From e93cbd13d51c59763476528bb2232903504f7457 Mon Sep 17 00:00:00 2001 From: "pbos@webrtc.org" Date: Wed, 15 Oct 2014 14:54:56 +0000 Subject: [PATCH] Fix data races in ThreadTest.ThreeThreadsInvoke. R=henrike@webrtc.org BUG= Review URL: https://webrtc-codereview.appspot.com/26819004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@7457 4adac7df-926f-26a2-2b94-8c16560cd09d --- webrtc/base/thread_unittest.cc | 42 ++++++++++++++++++------ webrtc/build/tsan_suppressions_webrtc.cc | 1 - 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/webrtc/base/thread_unittest.cc b/webrtc/base/thread_unittest.cc index bab4f0f04d..951a7e14f3 100644 --- a/webrtc/base/thread_unittest.cc +++ b/webrtc/base/thread_unittest.cc @@ -313,42 +313,64 @@ TEST(ThreadTest, ThreeThreadsInvoke) { thread_b.Start(); thread_c.Start(); + class LockedBool { + public: + explicit LockedBool(bool value) : value_(value) {} + + void Set(bool value) { + CritScope lock(&crit_); + value_ = value; + } + + bool Get() { + CritScope lock(&crit_); + return value_; + } + + private: + CriticalSection crit_; + bool value_ GUARDED_BY(crit_); + }; + struct LocalFuncs { - static void Set(bool* out) { *out = true; } - static void InvokeSet(Thread* thread, bool* out) { + static void Set(LockedBool* out) { out->Set(true); } + static void InvokeSet(Thread* thread, LockedBool* out) { thread->Invoke(Bind(&Set, out)); } // Set |out| true and call InvokeSet on |thread|. - static void SetAndInvokeSet(bool* out, Thread* thread, bool* out_inner) { - *out = true; + static void SetAndInvokeSet(LockedBool* out, + Thread* thread, + LockedBool* out_inner) { + out->Set(true); InvokeSet(thread, out_inner); } // Asynchronously invoke SetAndInvokeSet on |thread1| and wait until // |thread1| starts the call. static void AsyncInvokeSetAndWait( - Thread* thread1, Thread* thread2, bool* out) { - bool async_invoked = false; + Thread* thread1, Thread* thread2, LockedBool* out) { + CriticalSection crit; + LockedBool async_invoked(false); AsyncInvoker invoker; invoker.AsyncInvoke( thread1, Bind(&SetAndInvokeSet, &async_invoked, thread2, out)); - EXPECT_TRUE_WAIT(async_invoked, 2000); + EXPECT_TRUE_WAIT(async_invoked.Get(), 2000); } }; - bool thread_a_called = false; + LockedBool thread_a_called(false); // Start the sequence A --(invoke)--> B --(async invoke)--> C --(invoke)--> A. // Thread B returns when C receives the call and C should be blocked until A // starts to process messages. thread_b.Invoke(Bind(&LocalFuncs::AsyncInvokeSetAndWait, &thread_c, thread_a, &thread_a_called)); - EXPECT_FALSE(thread_a_called); + EXPECT_FALSE(thread_a_called.Get()); - EXPECT_TRUE_WAIT(thread_a_called, 2000); + EXPECT_TRUE_WAIT(thread_a_called.Get(), 2000); } class AsyncInvokeTest : public testing::Test { diff --git a/webrtc/build/tsan_suppressions_webrtc.cc b/webrtc/build/tsan_suppressions_webrtc.cc index 8ec7149958..01658ed246 100644 --- a/webrtc/build/tsan_suppressions_webrtc.cc +++ b/webrtc/build/tsan_suppressions_webrtc.cc @@ -44,7 +44,6 @@ char kTSanDefaultSuppressions[] = // rtc_unittest // https://code.google.com/p/webrtc/issues/detail?id=3911 for details. -"race:ThreadTest_ThreeThreadsInvoke_Test::TestBody()::LocalFuncs::SetAndInvokeSet\n" "race:rtc::FireAndForgetAsyncClosure::Execute\n" "race:rtc::MessageQueueManager::Clear\n" "race:rtc::Thread::Clear\n"