diff options
author | wangxianzhu <wangxianzhu@chromium.org> | 2014-09-03 09:09:19 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-09-03 16:15:54 +0000 |
commit | bb113630cf9e1290eb211e8f9413f9dc4d4c5aab (patch) | |
tree | 7bc00980f80e9b8c32c3f51476489e75dd04c7ac /base | |
parent | 4e7c1817734ef4ccf8749fffe3cb4e18be1f1e5a (diff) | |
download | chromium_src-bb113630cf9e1290eb211e8f9413f9dc4d4c5aab.zip chromium_src-bb113630cf9e1290eb211e8f9413f9dc4d4c5aab.tar.gz chromium_src-bb113630cf9e1290eb211e8f9413f9dc4d4c5aab.tar.bz2 |
Avoid deadlock during trace_event flush
The deadlock occurs because we hold lock when posting flush tasks.
If MessageLoop::PostTask() also calls TRACE_EVENT and the TRACE_EVENT
has never been reached before, the TRACE_EVENT will try to get the
category enabled flag which will also need a lock.
Copy thread_message_loops into a temporary vector of
scoped_refptr<SingleProcessTaskRunner> to avoid lock when calling
PostTask().
BUG=397022
TEST=Existing tests and ThreadSanitizer
Review URL: https://codereview.chromium.org/491393002
Cr-Commit-Position: refs/heads/master@{#293144}
Diffstat (limited to 'base')
-rw-r--r-- | base/debug/trace_event_impl.cc | 23 |
1 files changed, 16 insertions, 7 deletions
diff --git a/base/debug/trace_event_impl.cc b/base/debug/trace_event_impl.cc index cce900c..db321e2 100644 --- a/base/debug/trace_event_impl.cc +++ b/base/debug/trace_event_impl.cc @@ -1697,6 +1697,9 @@ void TraceLog::Flush(const TraceLog::OutputCallback& cb) { } int generation = this->generation(); + // Copy of thread_message_loops_ to be used without locking. + std::vector<scoped_refptr<SingleThreadTaskRunner> > + thread_message_loop_task_runners; { AutoLock lock(lock_); DCHECK(!flush_message_loop_proxy_.get()); @@ -1713,16 +1716,22 @@ void TraceLog::Flush(const TraceLog::OutputCallback& cb) { for (hash_set<MessageLoop*>::const_iterator it = thread_message_loops_.begin(); it != thread_message_loops_.end(); ++it) { - (*it)->PostTask( - FROM_HERE, - Bind(&TraceLog::FlushCurrentThread, Unretained(this), generation)); + thread_message_loop_task_runners.push_back((*it)->task_runner()); } - flush_message_loop_proxy_->PostDelayedTask( + } + } + + if (thread_message_loop_task_runners.size()) { + for (size_t i = 0; i < thread_message_loop_task_runners.size(); ++i) { + thread_message_loop_task_runners[i]->PostTask( FROM_HERE, - Bind(&TraceLog::OnFlushTimeout, Unretained(this), generation), - TimeDelta::FromMilliseconds(kThreadFlushTimeoutMs)); - return; + Bind(&TraceLog::FlushCurrentThread, Unretained(this), generation)); } + flush_message_loop_proxy_->PostDelayedTask( + FROM_HERE, + Bind(&TraceLog::OnFlushTimeout, Unretained(this), generation), + TimeDelta::FromMilliseconds(kThreadFlushTimeoutMs)); + return; } FinishFlush(generation); |