Skip to content

Commit

Permalink
Fix --trace-shutdown with thread-local tracing.
Browse files Browse the repository at this point in the history
With thread-local tracing (r221766), TraceLog::Flush() is async and
needs to be called from a thread having a message loop. It also requires
that tracing has been stopped.

BrowserShutdownProfileDumper is a special caller that TraceLog::Flush()
was originally called from a thread without message loop.

Now start another thread for flushing, and call TraceLog::SetDisabled()
before TraceLog::Flush().

The calling thread needs to wait for the completion of the flush,
otherwise the browser may shutdown before all trace events written.
Temporarily allow the thread to wait in ThreadRestrictions.

BUG=none
TEST=manual run chrome with --trace-shutdown. Should not assert. Should generate correct trace file.

Review URL: https://chromiumcodereview.appspot.com/24047007

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@223819 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
wangxianzhu@chromium.org committed Sep 18, 2013
1 parent c963883 commit f9be105
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 2 deletions.
1 change: 1 addition & 0 deletions base/debug/trace_event_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1334,6 +1334,7 @@ void TraceLog::Flush(const TraceLog::OutputCallback& cb) {
scoped_refptr<RefCountedString> empty_result = new RefCountedString;
if (!cb.is_null())
cb.Run(empty_result, false);
LOG(WARNING) << "Ignored TraceLog::Flush called when tracing is enabled";
return;
}

Expand Down
2 changes: 2 additions & 0 deletions base/threading/thread_restrictions.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class Predictor;
}
namespace content {
class BrowserGpuChannelHostFactory;
class BrowserShutdownProfileDumper;
class BrowserTestBase;
class GLHelper;
class GpuChannelHost;
Expand Down Expand Up @@ -176,6 +177,7 @@ class BASE_EXPORT ThreadRestrictions {
private:
// DO NOT ADD ANY OTHER FRIEND STATEMENTS, talk to jam or brettw first.
// BEGIN ALLOWED USAGE.
friend class content::BrowserShutdownProfileDumper;
friend class content::BrowserTestBase;
friend class content::NestedMessagePumpAndroid;
friend class content::RenderWidgetHelper;
Expand Down
33 changes: 31 additions & 2 deletions content/browser/browser_shutdown_profile_dumper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
#include "content/public/common/content_switches.h"

namespace content {
Expand Down Expand Up @@ -43,9 +46,31 @@ void BrowserShutdownProfileDumper::WriteTracesToDisc(
WriteString("{\"traceEvents\":");
WriteString("[");

// TraceLog::Flush() requires the calling thread to have a message loop.
// As the message loop of the current thread may have quit, start another
// thread for flushing the trace.
base::WaitableEvent flush_complete_event(false, false);
base::Thread flush_thread("browser_shutdown_trace_event_flush");
flush_thread.Start();
flush_thread.message_loop()->PostTask(
FROM_HERE,
base::Bind(&BrowserShutdownProfileDumper::EndTraceAndFlush,
base::Unretained(this),
base::Unretained(&flush_complete_event)));

bool original_wait_allowed = base::ThreadRestrictions::SetWaitAllowed(true);
flush_complete_event.Wait();
base::ThreadRestrictions::SetWaitAllowed(original_wait_allowed);
}

void BrowserShutdownProfileDumper::EndTraceAndFlush(
base::WaitableEvent* flush_complete_event) {
while (base::debug::TraceLog::GetInstance()->IsEnabled())
base::debug::TraceLog::GetInstance()->SetDisabled();
base::debug::TraceLog::GetInstance()->Flush(
base::Bind(&BrowserShutdownProfileDumper::WriteTraceDataCollected,
base::Unretained(this)));
base::Unretained(this),
base::Unretained(flush_complete_event)));
}

base::FilePath BrowserShutdownProfileDumper::GetFileName() {
Expand All @@ -61,10 +86,13 @@ base::FilePath BrowserShutdownProfileDumper::GetFileName() {
}

void BrowserShutdownProfileDumper::WriteTraceDataCollected(
base::WaitableEvent* flush_complete_event,
const scoped_refptr<base::RefCountedString>& events_str,
bool has_more_events) {
if (!IsFileValid())
if (!IsFileValid()) {
flush_complete_event->Signal();
return;
}
if (blocks_) {
// Blocks are not comma separated. Beginning with the second block we
// start therefore to add one in front of the previous block.
Expand All @@ -77,6 +105,7 @@ void BrowserShutdownProfileDumper::WriteTraceDataCollected(
WriteString("]");
WriteString("}");
CloseFile();
flush_complete_event->Signal();
}
}

Expand Down
4 changes: 4 additions & 0 deletions content/browser/browser_shutdown_profile_dumper.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

namespace base {
class FilePath;
class WaitableEvent;
}

namespace content {
Expand All @@ -36,12 +37,15 @@ class BrowserShutdownProfileDumper {
// Writes all traces which happened to disk.
void WriteTracesToDisc(const base::FilePath& file_name);

void EndTraceAndFlush(base::WaitableEvent* flush_complete_event);

// Returns the file name where we should save the trace dump to.
base::FilePath GetFileName();

// The callback for the |TraceLog::Flush| function. It saves all traces to
// disc.
void WriteTraceDataCollected(
base::WaitableEvent* flush_complete_event,
const scoped_refptr<base::RefCountedString>& events_str,
bool has_more_events);

Expand Down

0 comments on commit f9be105

Please sign in to comment.