summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
authorwangxianzhu <wangxianzhu@chromium.org>2014-09-03 09:09:19 -0700
committerCommit bot <commit-bot@chromium.org>2014-09-03 16:15:54 +0000
commitbb113630cf9e1290eb211e8f9413f9dc4d4c5aab (patch)
tree7bc00980f80e9b8c32c3f51476489e75dd04c7ac /base
parent4e7c1817734ef4ccf8749fffe3cb4e18be1f1e5a (diff)
downloadchromium_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.cc23
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);