1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
11 #include "base/base_switches.h"
12 #include "base/bind.h"
13 #include "base/command_line.h"
14 #include "base/files/file_util.h"
15 #include "base/message_loop/message_loop.h"
16 #include "base/synchronization/waitable_event.h"
17 #include "base/trace_event/trace_event.h"
18 #include "components/tracing/startup_tracing.h"
19 #include "mojo/runner/context.h"
20 #include "mojo/runner/switches.h"
26 // Whether we're currently tracing.
27 bool g_tracing
= false;
29 // Number of tracing blocks written.
30 uint32_t g_blocks
= 0;
32 // Trace file, if open.
33 FILE* g_trace_file
= nullptr;
35 void WriteTraceDataCollected(
36 base::WaitableEvent
* event
,
37 const scoped_refptr
<base::RefCountedString
>& events_str
,
38 bool has_more_events
) {
40 fwrite(",", 1, 1, g_trace_file
);
44 fwrite(events_str
->data().c_str(), 1, events_str
->data().length(),
46 if (!has_more_events
) {
47 static const char kEnd
[] = "]}";
48 fwrite(kEnd
, 1, strlen(kEnd
), g_trace_file
);
49 PCHECK(fclose(g_trace_file
) == 0);
50 g_trace_file
= nullptr;
55 void EndTraceAndFlush(base::WaitableEvent
* event
) {
56 g_trace_file
= fopen("mojo_shell.trace", "w+");
58 static const char kStart
[] = "{\"traceEvents\":[";
59 fwrite(kStart
, 1, strlen(kStart
), g_trace_file
);
60 base::trace_event::TraceLog::GetInstance()->SetDisabled();
61 base::trace_event::TraceLog::GetInstance()->Flush(
62 base::Bind(&WriteTraceDataCollected
, base::Unretained(event
)));
65 void StopTracingAndFlushToDisk() {
67 base::trace_event::TraceLog::GetInstance()->SetDisabled();
68 base::WaitableEvent
flush_complete_event(false, false);
69 // TraceLog::Flush requires a message loop but we've already shut ours down.
70 // Spin up a new thread to flush things out.
71 base::Thread
flush_thread("mojo_shell_trace_event_flush");
73 flush_thread
.message_loop()->PostTask(
75 base::Bind(EndTraceAndFlush
, base::Unretained(&flush_complete_event
)));
76 flush_complete_event
.Wait();
81 int LauncherProcessMain(int argc
, char** argv
) {
82 const base::CommandLine
& command_line
=
83 *base::CommandLine::ForCurrentProcess();
84 if (command_line
.HasSwitch(switches::kTraceStartup
)) {
86 base::trace_event::TraceConfig
trace_config(
87 command_line
.GetSwitchValueASCII(switches::kTraceStartup
),
88 base::trace_event::RECORD_UNTIL_FULL
);
89 base::trace_event::TraceLog::GetInstance()->SetEnabled(
90 trace_config
, base::trace_event::TraceLog::RECORDING_MODE
);
92 // |g_tracing| is not touched in this case and Telemetry will stop tracing
94 tracing::EnableStartupTracingIfConfigFileExists();
97 // We want the shell::Context to outlive the MessageLoop so that pipes are
98 // all gracefully closed / error-out before we try to shut the Context down.
99 Context shell_context
;
101 base::MessageLoop message_loop
;
102 if (!shell_context
.Init()) {
106 message_loop
.PostDelayedTask(FROM_HERE
,
107 base::Bind(StopTracingAndFlushToDisk
),
108 base::TimeDelta::FromSeconds(5));
111 message_loop
.PostTask(
113 base::Bind(&Context::RunCommandLineApplication
,
114 base::Unretained(&shell_context
), base::Closure()));
117 // Must be called before |message_loop| is destroyed.
118 shell_context
.Shutdown();
122 StopTracingAndFlushToDisk();
126 } // namespace runner