Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(195)

Side by Side Diff: content/browser/browser_main_runner.cc

Issue 23691025: Adding shutdown tracing capabilities (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/public/browser/browser_main_runner.h" 5 #include "content/public/browser/browser_main_runner.h"
6 6
7 #include "base/allocator/allocator_shim.h" 7 #include "base/allocator/allocator_shim.h"
8 #include "base/base_switches.h" 8 #include "base/base_switches.h"
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/debug/trace_event.h" 10 #include "base/debug/trace_event.h"
11 #include "base/debug/trace_event_impl.h"
12 #include "base/file_util.h"
13 #include "base/files/file_path.h"
11 #include "base/logging.h" 14 #include "base/logging.h"
12 #include "base/metrics/histogram.h" 15 #include "base/metrics/histogram.h"
13 #include "base/metrics/statistics_recorder.h" 16 #include "base/metrics/statistics_recorder.h"
14 #include "content/browser/browser_main_loop.h" 17 #include "content/browser/browser_main_loop.h"
15 #include "content/browser/notification_service_impl.h" 18 #include "content/browser/notification_service_impl.h"
16 #include "content/public/common/content_switches.h" 19 #include "content/public/common/content_switches.h"
17 #include "content/public/common/main_function_params.h" 20 #include "content/public/common/main_function_params.h"
18 #include "ui/base/ime/input_method_initializer.h" 21 #include "ui/base/ime/input_method_initializer.h"
19 22
20 #if defined(OS_WIN) 23 #if defined(OS_WIN)
21 #include "base/win/metro.h" 24 #include "base/win/metro.h"
22 #include "base/win/windows_version.h" 25 #include "base/win/windows_version.h"
23 #include "ui/base/win/scoped_ole_initializer.h" 26 #include "ui/base/win/scoped_ole_initializer.h"
24 #endif 27 #endif
25 28
26 bool g_exited_main_message_loop = false; 29 bool g_exited_main_message_loop = false;
27 30
31 namespace {
32
33 // This class is intended to initiate tracing of the shutdown procedure as well
34 // as dumping the resulting traces to a file before the browser process exits.
35 // It will save the file either into the command line passed
36 // "--trace-shutdown-file=<name>" parameter - or - to "chrometrace.log".
37 // Use the class with a scoped_ptr to automatically write the dump when the
38 // object gets destroyed.
39 // Note that we cannot use the asynchronous file writer since the
40 // |SequencedWorkerPool| will get killed in the shutdown process.
41 class BrowserShutdownProfilerAndDumper {
James Cook 2013/08/30 22:54:02 I think this class is big enough to go in a separa
Mr4D (OOO till 08-26) 2013/08/31 02:03:44 Done.
42 public:
43 BrowserShutdownProfilerAndDumper() : blocks_(0), dump_file_(0) {
44 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
45 base::debug::CategoryFilter category_filter(
46 command_line.GetSwitchValueASCII(switches::kTraceShutdown));
47 base::debug::TraceLog::GetInstance()->SetEnabled(
48 category_filter,
49 base::debug::TraceLog::RECORD_UNTIL_FULL);
50 }
51
52 virtual ~BrowserShutdownProfilerAndDumper() {
53 WriteTracesToDisc(GetFileName());
54 }
55
56 private:
57 // Writes all traces which happened to disc.
58 void WriteTracesToDisc(base::FilePath file_name) {
59 LOG(ERROR) << "Flushing shutdown traces to disc. The buffer is %" <<
James Cook 2013/08/30 22:54:02 Could this be a VLOG? Or is this slow enough that
Mr4D (OOO till 08-26) 2013/08/31 02:03:44 I did never run VLOG yet, but since you asked for
60 base::debug::TraceLog::GetInstance()->GetBufferPercentFull() <<
61 " full.";
62 DCHECK(!dump_file_);
63 dump_file_ = file_util::OpenFile(file_name, "w+");
64 if (!IsFileValid()) {
65 LOG(ERROR) << "Failed to open performance trace file: " <<
66 file_name.value();
67 return;
68 }
69 WriteString("{\"traceEvents\":");
70 WriteString("[");
71
72 base::debug::TraceLog::GetInstance()->Flush(
73 base::Bind(&BrowserShutdownProfilerAndDumper::WriteTraceDataCollected,
74 base::Unretained(this)));
75
76 WriteString("]");
77 WriteString("}");
78 CloseFile();
79 }
80
81 // Returns the file name where we should save the trace dump to.
82 base::FilePath GetFileName() {
83 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
84 base::FilePath trace_file =
85 command_line.GetSwitchValuePath(switches::kTraceShutdownFile);
86
87 if (!trace_file.empty())
88 return trace_file;
89
90 // Default to saving the startup trace into the current dir.
91 return base::FilePath().AppendASCII("chrometrace.log");
James Cook 2013/08/30 22:54:02 FYI - We usually use the suffix ".json" for trace
Mr4D (OOO till 08-26) 2013/08/31 02:03:44 I used the same default name as for the startup ca
92 }
93
94 // The callback for the |TraceLog::Flush| function. It saves all traces to
95 // disc.
96 void WriteTraceDataCollected(
97 const scoped_refptr<base::RefCountedString>& events_str) {
98 if (!IsFileValid())
99 return;
100 if (blocks_) {
101 // Blocks are not comma separated. Beginning with the second block we
102 // start therefore to add one in front of the previous block.
103 WriteString(",");
104 }
105 blocks_++;
106 WriteString(events_str->data());
107 }
108
109 // Returns true if the dump file is valid.
110 bool IsFileValid() {
111 return dump_file_ && (0 == ferror(dump_file_));
James Cook 2013/08/30 22:54:02 ferror(dump_file_) == 0
Mr4D (OOO till 08-26) 2013/08/31 02:03:44 Done.
112 }
113
114 // Writes a string to the dump file.
115 void WriteString(const std::string& string) {
116 WriteChars(string.data(), string.size());
117
James Cook 2013/08/30 22:54:02 no blank line
Mr4D (OOO till 08-26) 2013/08/31 02:03:44 Done.
118 }
119
120 // Write a buffer to the dump file.
121 void WriteChars(const char* chars, size_t size) {
122 if (!IsFileValid())
123 return;
124
125 size_t written = fwrite(chars, 1, size, dump_file_);
126 if (written != size) {
127 LOG(ERROR) << "Error " << ferror(dump_file_) <<
128 " in fwrite() to trace file";
129 CloseFile();
130 }
131 }
132
133 // Closes the dump file.
134 void CloseFile() {
135 if (!IsFileValid())
136 return;
137 fclose(dump_file_);
James Cook 2013/08/30 22:54:02 Use file_util::CloseFile()
Mr4D (OOO till 08-26) 2013/08/31 02:03:44 Done.
138 dump_file_ = 0;
139 }
140
141 // The number of blocks we have already written.
142 int blocks_;
143 // For dumping the content to disc.
144 FILE* dump_file_;
145 };
146
147 }
148
28 namespace content { 149 namespace content {
29 150
30 class BrowserMainRunnerImpl : public BrowserMainRunner { 151 class BrowserMainRunnerImpl : public BrowserMainRunner {
31 public: 152 public:
32 BrowserMainRunnerImpl() 153 BrowserMainRunnerImpl()
33 : initialization_started_(false), is_shutdown_(false) {} 154 : initialization_started_(false), is_shutdown_(false) {}
34 155
35 virtual ~BrowserMainRunnerImpl() { 156 virtual ~BrowserMainRunnerImpl() {
36 if (initialization_started_ && !is_shutdown_) 157 if (initialization_started_ && !is_shutdown_)
37 Shutdown(); 158 Shutdown();
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 } 236 }
116 237
117 virtual int Run() OVERRIDE { 238 virtual int Run() OVERRIDE {
118 DCHECK(initialization_started_); 239 DCHECK(initialization_started_);
119 DCHECK(!is_shutdown_); 240 DCHECK(!is_shutdown_);
120 main_loop_->RunMainMessageLoopParts(); 241 main_loop_->RunMainMessageLoopParts();
121 return main_loop_->GetResultCode(); 242 return main_loop_->GetResultCode();
122 } 243 }
123 244
124 virtual void Shutdown() OVERRIDE { 245 virtual void Shutdown() OVERRIDE {
125 DCHECK(initialization_started_); 246 // Enable shutdown tracing automatically upon shutdown if requested.
126 DCHECK(!is_shutdown_); 247 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
127 g_exited_main_message_loop = true; 248 // When the object gets destroyed the traces will get written to disc.
249 scoped_ptr<BrowserShutdownProfilerAndDumper> profiler;
250 if (command_line.HasSwitch(switches::kTraceShutdown))
251 profiler.reset(new BrowserShutdownProfilerAndDumper());
252 {
James Cook 2013/08/30 22:54:02 Put a blank line above this, or move the comment f
Mr4D (OOO till 08-26) 2013/08/31 02:03:44 Did that already in the following patch. Done.
253 // The trace event has to stay between profiler creation and destruction.
254 TRACE_EVENT0("shutdown", "BrowserMainRunner");
255 DCHECK(initialization_started_);
256 DCHECK(!is_shutdown_);
257 g_exited_main_message_loop = true;
128 258
129 main_loop_->ShutdownThreadsAndCleanUp(); 259 main_loop_->ShutdownThreadsAndCleanUp();
130 260
131 ui::ShutdownInputMethod(); 261 ui::ShutdownInputMethod();
132 #if defined(OS_WIN) 262 #if defined(OS_WIN)
133 ole_initializer_.reset(NULL); 263 ole_initializer_.reset(NULL);
134 #endif 264 #endif
135 265
136 main_loop_.reset(NULL); 266 main_loop_.reset(NULL);
137 267
138 notification_service_.reset(NULL); 268 notification_service_.reset(NULL);
139 269
140 is_shutdown_ = true; 270 is_shutdown_ = true;
271 }
141 } 272 }
142 273
143 protected: 274 protected:
144 // True if we have started to initialize the runner. 275 // True if we have started to initialize the runner.
145 bool initialization_started_; 276 bool initialization_started_;
146 277
147 // True if the runner has been shut down. 278 // True if the runner has been shut down.
148 bool is_shutdown_; 279 bool is_shutdown_;
149 280
150 scoped_ptr<NotificationServiceImpl> notification_service_; 281 scoped_ptr<NotificationServiceImpl> notification_service_;
151 scoped_ptr<BrowserMainLoop> main_loop_; 282 scoped_ptr<BrowserMainLoop> main_loop_;
152 #if defined(OS_WIN) 283 #if defined(OS_WIN)
153 scoped_ptr<ui::ScopedOleInitializer> ole_initializer_; 284 scoped_ptr<ui::ScopedOleInitializer> ole_initializer_;
154 #endif 285 #endif
155 286
156 DISALLOW_COPY_AND_ASSIGN(BrowserMainRunnerImpl); 287 DISALLOW_COPY_AND_ASSIGN(BrowserMainRunnerImpl);
157 }; 288 };
158 289
159 // static 290 // static
160 BrowserMainRunner* BrowserMainRunner::Create() { 291 BrowserMainRunner* BrowserMainRunner::Create() {
161 return new BrowserMainRunnerImpl(); 292 return new BrowserMainRunnerImpl();
162 } 293 }
163 294
164 } // namespace content 295 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698