Commit 41bc6681 authored by haraken@chromium.org's avatar haraken@chromium.org

Avoid threading races on TraceSamplingThread's members

The original CL was landed in https://codereview.chromium.org/26541005/
but the CL caused a dead lock. This CL fixed the issue.

NOTRY=true

Review URL: https://codereview.chromium.org/28593003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@233266 0039d316-1c4b-4281-b951-d872f2087c98
parent d885fd84
...@@ -838,7 +838,7 @@ class TraceSamplingThread : public PlatformThread::Delegate { ...@@ -838,7 +838,7 @@ class TraceSamplingThread : public PlatformThread::Delegate {
static void DefaultSamplingCallback(TraceBucketData* bucekt_data); static void DefaultSamplingCallback(TraceBucketData* bucekt_data);
void Stop(); void Stop();
void InstallWaitableEventForSamplingTesting(WaitableEvent* waitable_event); void WaitSamplingEventForTesting();
private: private:
friend class TraceLog; friend class TraceLog;
...@@ -855,14 +855,14 @@ class TraceSamplingThread : public PlatformThread::Delegate { ...@@ -855,14 +855,14 @@ class TraceSamplingThread : public PlatformThread::Delegate {
const char** name); const char** name);
std::vector<TraceBucketData> sample_buckets_; std::vector<TraceBucketData> sample_buckets_;
bool thread_running_; bool thread_running_;
scoped_ptr<CancellationFlag> cancellation_flag_; CancellationFlag cancellation_flag_;
scoped_ptr<WaitableEvent> waitable_event_for_testing_; WaitableEvent waitable_event_for_testing_;
}; };
TraceSamplingThread::TraceSamplingThread() TraceSamplingThread::TraceSamplingThread()
: thread_running_(false) { : thread_running_(false),
cancellation_flag_.reset(new CancellationFlag); waitable_event_for_testing_(false, false) {
} }
TraceSamplingThread::~TraceSamplingThread() { TraceSamplingThread::~TraceSamplingThread() {
...@@ -872,12 +872,11 @@ void TraceSamplingThread::ThreadMain() { ...@@ -872,12 +872,11 @@ void TraceSamplingThread::ThreadMain() {
PlatformThread::SetName("Sampling Thread"); PlatformThread::SetName("Sampling Thread");
thread_running_ = true; thread_running_ = true;
const int kSamplingFrequencyMicroseconds = 1000; const int kSamplingFrequencyMicroseconds = 1000;
while (!cancellation_flag_->IsSet()) { while (!cancellation_flag_.IsSet()) {
PlatformThread::Sleep( PlatformThread::Sleep(
TimeDelta::FromMicroseconds(kSamplingFrequencyMicroseconds)); TimeDelta::FromMicroseconds(kSamplingFrequencyMicroseconds));
GetSamples(); GetSamples();
if (waitable_event_for_testing_.get()) waitable_event_for_testing_.Signal();
waitable_event_for_testing_->Signal();
} }
} }
...@@ -909,6 +908,9 @@ void TraceSamplingThread::RegisterSampleBucket( ...@@ -909,6 +908,9 @@ void TraceSamplingThread::RegisterSampleBucket(
TRACE_EVENT_API_ATOMIC_WORD* bucket, TRACE_EVENT_API_ATOMIC_WORD* bucket,
const char* const name, const char* const name,
TraceSampleCallback callback) { TraceSampleCallback callback) {
// Access to sample_buckets_ doesn't cause races with the sampling thread
// that uses the sample_buckets_, because it is guaranteed that
// RegisterSampleBucket is called before the sampling thread is created.
DCHECK(!thread_running_); DCHECK(!thread_running_);
sample_buckets_.push_back(TraceBucketData(bucket, name, callback)); sample_buckets_.push_back(TraceBucketData(bucket, name, callback));
} }
...@@ -922,12 +924,11 @@ void TraceSamplingThread::ExtractCategoryAndName(const char* combined, ...@@ -922,12 +924,11 @@ void TraceSamplingThread::ExtractCategoryAndName(const char* combined,
} }
void TraceSamplingThread::Stop() { void TraceSamplingThread::Stop() {
cancellation_flag_->Set(); cancellation_flag_.Set();
} }
void TraceSamplingThread::InstallWaitableEventForSamplingTesting( void TraceSamplingThread::WaitSamplingEventForTesting() {
WaitableEvent* waitable_event) { waitable_event_for_testing_.Wait();
waitable_event_for_testing_.reset(waitable_event);
} }
TraceBucketData::TraceBucketData(base::subtle::AtomicWord* bucket, TraceBucketData::TraceBucketData(base::subtle::AtomicWord* bucket,
...@@ -2027,11 +2028,10 @@ void TraceLog::AddMetadataEventsWhileLocked() { ...@@ -2027,11 +2028,10 @@ void TraceLog::AddMetadataEventsWhileLocked() {
} }
} }
void TraceLog::InstallWaitableEventForSamplingTesting( void TraceLog::WaitSamplingEventForTesting() {
WaitableEvent* waitable_event) {
if (!sampling_thread_) if (!sampling_thread_)
return; return;
sampling_thread_->InstallWaitableEventForSamplingTesting(waitable_event); sampling_thread_->WaitSamplingEventForTesting();
} }
void TraceLog::DeleteForTesting() { void TraceLog::DeleteForTesting() {
......
...@@ -540,7 +540,7 @@ class BASE_EXPORT TraceLog { ...@@ -540,7 +540,7 @@ class BASE_EXPORT TraceLog {
// Exposed for unittesting: // Exposed for unittesting:
void InstallWaitableEventForSamplingTesting(WaitableEvent* waitable_event); void WaitSamplingEventForTesting();
// Allows deleting our singleton instance. // Allows deleting our singleton instance.
static void DeleteForTesting(); static void DeleteForTesting();
......
...@@ -1756,13 +1756,10 @@ TEST_F(TraceEventTestFixture, TraceSampling) { ...@@ -1756,13 +1756,10 @@ TEST_F(TraceEventTestFixture, TraceSampling) {
TraceLog::Options(TraceLog::RECORD_UNTIL_FULL | TraceLog::Options(TraceLog::RECORD_UNTIL_FULL |
TraceLog::ENABLE_SAMPLING)); TraceLog::ENABLE_SAMPLING));
WaitableEvent* sampled = new WaitableEvent(false, false);
TraceLog::GetInstance()->InstallWaitableEventForSamplingTesting(sampled);
TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(1, "cc", "Stuff"); TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(1, "cc", "Stuff");
sampled->Wait(); TraceLog::GetInstance()->WaitSamplingEventForTesting();
TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(1, "cc", "Things"); TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(1, "cc", "Things");
sampled->Wait(); TraceLog::GetInstance()->WaitSamplingEventForTesting();
EndTraceAndFlush(); EndTraceAndFlush();
...@@ -1778,32 +1775,29 @@ TEST_F(TraceEventTestFixture, TraceSamplingScope) { ...@@ -1778,32 +1775,29 @@ TEST_F(TraceEventTestFixture, TraceSamplingScope) {
TraceLog::Options(TraceLog::RECORD_UNTIL_FULL | TraceLog::Options(TraceLog::RECORD_UNTIL_FULL |
TraceLog::ENABLE_SAMPLING)); TraceLog::ENABLE_SAMPLING));
WaitableEvent* sampled = new WaitableEvent(false, false);
TraceLog::GetInstance()->InstallWaitableEventForSamplingTesting(sampled);
TRACE_EVENT_SCOPED_SAMPLING_STATE("AAA", "name"); TRACE_EVENT_SCOPED_SAMPLING_STATE("AAA", "name");
sampled->Wait(); TraceLog::GetInstance()->WaitSamplingEventForTesting();
{ {
EXPECT_STREQ(TRACE_EVENT_GET_SAMPLING_STATE(), "AAA"); EXPECT_STREQ(TRACE_EVENT_GET_SAMPLING_STATE(), "AAA");
TRACE_EVENT_SCOPED_SAMPLING_STATE("BBB", "name"); TRACE_EVENT_SCOPED_SAMPLING_STATE("BBB", "name");
sampled->Wait(); TraceLog::GetInstance()->WaitSamplingEventForTesting();
EXPECT_STREQ(TRACE_EVENT_GET_SAMPLING_STATE(), "BBB"); EXPECT_STREQ(TRACE_EVENT_GET_SAMPLING_STATE(), "BBB");
} }
sampled->Wait(); TraceLog::GetInstance()->WaitSamplingEventForTesting();
{ {
EXPECT_STREQ(TRACE_EVENT_GET_SAMPLING_STATE(), "AAA"); EXPECT_STREQ(TRACE_EVENT_GET_SAMPLING_STATE(), "AAA");
TRACE_EVENT_SCOPED_SAMPLING_STATE("CCC", "name"); TRACE_EVENT_SCOPED_SAMPLING_STATE("CCC", "name");
sampled->Wait(); TraceLog::GetInstance()->WaitSamplingEventForTesting();
EXPECT_STREQ(TRACE_EVENT_GET_SAMPLING_STATE(), "CCC"); EXPECT_STREQ(TRACE_EVENT_GET_SAMPLING_STATE(), "CCC");
} }
sampled->Wait(); TraceLog::GetInstance()->WaitSamplingEventForTesting();
{ {
EXPECT_STREQ(TRACE_EVENT_GET_SAMPLING_STATE(), "AAA"); EXPECT_STREQ(TRACE_EVENT_GET_SAMPLING_STATE(), "AAA");
TRACE_EVENT_SET_SAMPLING_STATE("DDD", "name"); TRACE_EVENT_SET_SAMPLING_STATE("DDD", "name");
sampled->Wait(); TraceLog::GetInstance()->WaitSamplingEventForTesting();
EXPECT_STREQ(TRACE_EVENT_GET_SAMPLING_STATE(), "DDD"); EXPECT_STREQ(TRACE_EVENT_GET_SAMPLING_STATE(), "DDD");
} }
sampled->Wait(); TraceLog::GetInstance()->WaitSamplingEventForTesting();
EXPECT_STREQ(TRACE_EVENT_GET_SAMPLING_STATE(), "DDD"); EXPECT_STREQ(TRACE_EVENT_GET_SAMPLING_STATE(), "DDD");
EndTraceAndFlush(); EndTraceAndFlush();
...@@ -1815,14 +1809,10 @@ TEST_F(TraceEventTestFixture, TraceContinuousSampling) { ...@@ -1815,14 +1809,10 @@ TEST_F(TraceEventTestFixture, TraceContinuousSampling) {
CategoryFilter("*"), CategoryFilter("*"),
TraceLog::Options(TraceLog::MONITOR_SAMPLING)); TraceLog::Options(TraceLog::MONITOR_SAMPLING));
WaitableEvent* sampled = new WaitableEvent(false, false);
TraceLog::GetInstance()->InstallWaitableEventForSamplingTesting(
sampled);
TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(1, "category", "AAA"); TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(1, "category", "AAA");
sampled->Wait(); TraceLog::GetInstance()->WaitSamplingEventForTesting();
TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(1, "category", "BBB"); TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(1, "category", "BBB");
sampled->Wait(); TraceLog::GetInstance()->WaitSamplingEventForTesting();
FlushMonitoring(); FlushMonitoring();
...@@ -1831,12 +1821,12 @@ TEST_F(TraceEventTestFixture, TraceContinuousSampling) { ...@@ -1831,12 +1821,12 @@ TEST_F(TraceEventTestFixture, TraceContinuousSampling) {
EXPECT_TRUE(FindNamePhase("BBB", "P")); EXPECT_TRUE(FindNamePhase("BBB", "P"));
Clear(); Clear();
sampled->Wait(); TraceLog::GetInstance()->WaitSamplingEventForTesting();
TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(1, "category", "CCC"); TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(1, "category", "CCC");
sampled->Wait(); TraceLog::GetInstance()->WaitSamplingEventForTesting();
TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(1, "category", "DDD"); TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(1, "category", "DDD");
sampled->Wait(); TraceLog::GetInstance()->WaitSamplingEventForTesting();
FlushMonitoring(); FlushMonitoring();
......
...@@ -59,9 +59,6 @@ race:uprv_realloc_46 ...@@ -59,9 +59,6 @@ race:uprv_realloc_46
# http://crbug.com/223955 # http://crbug.com/223955
race:PassRefPtr race:PassRefPtr
# http://crbug.com/224617
race:base::debug::TraceEventTestFixture_TraceSampling_Test::TestBody
# http://crbug.com/239359 # http://crbug.com/239359
race:media::TestInputCallback::OnData race:media::TestInputCallback::OnData
...@@ -135,8 +132,5 @@ race:PostponeInterruptsScope ...@@ -135,8 +132,5 @@ race:PostponeInterruptsScope
# http://crbug.com/296883 # http://crbug.com/296883
race:net::URLFetcherCore::Stop race:net::URLFetcherCore::Stop
# http://crbug.com/305459
race:base::debug::TraceEventTestFixture_TraceContinuousSampling_Test::TestBody
# http://crbug.com/310851 # http://crbug.com/310851
race:net::ProxyResolverV8Tracing::Job::~Job race:net::ProxyResolverV8Tracing::Job::~Job
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment