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

Side by Side Diff: chrome/browser/process_singleton_win.cc

Issue 2871793003: Added histograms on process singleton create when remote process exists and we cannot notify it (Closed)
Patch Set: Created 3 years, 7 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
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 "chrome/browser/process_singleton.h" 5 #include "chrome/browser/process_singleton.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 #include <shellapi.h> 8 #include <shellapi.h>
9 #include <stddef.h> 9 #include <stddef.h>
10 10
11 #include "base/base_paths.h" 11 #include "base/base_paths.h"
12 #include "base/bind.h" 12 #include "base/bind.h"
13 #include "base/command_line.h" 13 #include "base/command_line.h"
14 #include "base/debug/activity_tracker.h"
14 #include "base/files/file_path.h" 15 #include "base/files/file_path.h"
15 #include "base/macros.h" 16 #include "base/macros.h"
16 #include "base/metrics/histogram_macros.h" 17 #include "base/metrics/histogram_macros.h"
17 #include "base/process/process.h" 18 #include "base/process/process.h"
18 #include "base/process/process_info.h" 19 #include "base/process/process_info.h"
19 #include "base/strings/string_number_conversions.h" 20 #include "base/strings/string_number_conversions.h"
20 #include "base/strings/utf_string_conversions.h" 21 #include "base/strings/utf_string_conversions.h"
21 #include "base/time/time.h" 22 #include "base/time/time.h"
22 #include "base/win/registry.h" 23 #include "base/win/registry.h"
23 #include "base/win/scoped_handle.h" 24 #include "base/win/scoped_handle.h"
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
171 return true; 172 return true;
172 } 173 }
173 174
174 bool DisplayShouldKillMessageBox() { 175 bool DisplayShouldKillMessageBox() {
175 return chrome::ShowQuestionMessageBox( 176 return chrome::ShowQuestionMessageBox(
176 NULL, l10n_util::GetStringUTF16(IDS_PRODUCT_NAME), 177 NULL, l10n_util::GetStringUTF16(IDS_PRODUCT_NAME),
177 l10n_util::GetStringUTF16(IDS_BROWSER_HUNGBROWSER_MESSAGE)) != 178 l10n_util::GetStringUTF16(IDS_BROWSER_HUNGBROWSER_MESSAGE)) !=
178 chrome::MESSAGE_BOX_RESULT_NO; 179 chrome::MESSAGE_BOX_RESULT_NO;
179 } 180 }
180 181
182 // Function was copied from Process::Terminate.
183 void TerminateProcessWithHistograms(const base::Process& process,
184 int exit_code) {
185 DCHECK(process.IsValid());
186 base::TimeTicks start_time = base::TimeTicks::Now();
187 bool result = (::TerminateProcess(process.Handle(), exit_code) != FALSE);
188 DWORD terminate_error = 0;
189 if (result) {
190 DWORD wait_error = 0;
191 // The process may not end immediately due to pending I/O
192 DWORD wait_result = ::WaitForSingleObject(process.Handle(), 60 * 1000);
193 if (wait_result != WAIT_OBJECT_0) {
194 if (wait_result == WAIT_FAILED)
195 wait_error = ::GetLastError();
196 UMA_HISTOGRAM_ENUMERATION(
197 "Chrome.ProcessSingleton.RemoteProcessInteractionResult",
198 ProcessSingleton::TERMINATE_WAIT_TIMEOUT,
199 ProcessSingleton::MAX_HUNG_REMOTE_PROCESS_ACTION);
200 DPLOG(ERROR) << "Error waiting for process exit";
201 } else {
202 UMA_HISTOGRAM_ENUMERATION(
203 "Chrome.ProcessSingleton.RemoteProcessInteractionResult",
204 ProcessSingleton::TERMINATE_SUCCEEDED,
205 ProcessSingleton::MAX_HUNG_REMOTE_PROCESS_ACTION);
206 }
207 UMA_HISTOGRAM_TIMES("Chrome.ProcessSingleton.TerminateProcessTime",
208 base::TimeTicks::Now() - start_time);
209 UMA_HISTOGRAM_SPARSE_SLOWLY(
210 "Chrome.ProcessSingleton.TerminationWaitErrorCode.Windows", wait_error);
211 base::debug::GlobalActivityTracker::RecordProcessExitIfEnabled(
212 process.Pid(), exit_code);
213 } else {
214 terminate_error = ::GetLastError();
215 UMA_HISTOGRAM_ENUMERATION(
216 "Chrome.ProcessSingleton.RemoteProcessInteractionResult",
217 ProcessSingleton::TERMINATE_FAILED,
218 ProcessSingleton::MAX_HUNG_REMOTE_PROCESS_ACTION);
219 DPLOG(ERROR) << "Unable to terminate process";
220 }
221 UMA_HISTOGRAM_SPARSE_SLOWLY(
222 "Chrome.ProcessSingleton.ProcessTerminateErrorCode.Windows",
gab 2017/05/10 15:16:50 These histograms will be examined filtered per pla
Alexey Seren 2017/05/11 13:42:05 Unfortunately we cannot do it because each platfor
gab 2017/05/11 15:10:03 s/OSAgnosticErrno/PosixErrno/ (maybe there's alrea
223 terminate_error);
224 }
225
181 } // namespace 226 } // namespace
182 227
183 // Microsoft's Softricity virtualization breaks the sandbox processes. 228 // Microsoft's Softricity virtualization breaks the sandbox processes.
184 // So, if we detect the Softricity DLL we use WMI Win32_Process.Create to 229 // So, if we detect the Softricity DLL we use WMI Win32_Process.Create to
185 // break out of the virtualization environment. 230 // break out of the virtualization environment.
186 // http://code.google.com/p/chromium/issues/detail?id=43650 231 // http://code.google.com/p/chromium/issues/detail?id=43650
187 bool ProcessSingleton::EscapeVirtualization( 232 bool ProcessSingleton::EscapeVirtualization(
188 const base::FilePath& user_data_dir) { 233 const base::FilePath& user_data_dir) {
189 if (::GetModuleHandle(L"sftldr_wow64.dll") || 234 if (::GetModuleHandle(L"sftldr_wow64.dll") ||
190 ::GetModuleHandle(L"sftldr.dll")) { 235 ::GetModuleHandle(L"sftldr.dll")) {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
235 return LOCK_ERROR; 280 return LOCK_ERROR;
236 } else if (!remote_window_) { 281 } else if (!remote_window_) {
237 return PROCESS_NONE; 282 return PROCESS_NONE;
238 } 283 }
239 284
240 switch (chrome::AttemptToNotifyRunningChrome(remote_window_, false)) { 285 switch (chrome::AttemptToNotifyRunningChrome(remote_window_, false)) {
241 case chrome::NOTIFY_SUCCESS: 286 case chrome::NOTIFY_SUCCESS:
242 return PROCESS_NOTIFIED; 287 return PROCESS_NOTIFIED;
243 case chrome::NOTIFY_FAILED: 288 case chrome::NOTIFY_FAILED:
244 remote_window_ = NULL; 289 remote_window_ = NULL;
290 UMA_HISTOGRAM_ENUMERATION(
291 "Chrome.ProcessSingleton.RemoteProcessInteractionResult",
292 RUNNING_PROCESS_NOTIFY_FAILED, MAX_HUNG_REMOTE_PROCESS_ACTION);
245 return PROCESS_NONE; 293 return PROCESS_NONE;
246 case chrome::NOTIFY_WINDOW_HUNG: 294 case chrome::NOTIFY_WINDOW_HUNG:
247 // Fall through and potentially terminate the hung browser. 295 // Fall through and potentially terminate the hung browser.
248 break; 296 break;
249 } 297 }
250 298
251 // The window is hung. 299 // The window is hung.
252 DWORD process_id = 0; 300 DWORD process_id = 0;
253 DWORD thread_id = ::GetWindowThreadProcessId(remote_window_, &process_id); 301 DWORD thread_id = ::GetWindowThreadProcessId(remote_window_, &process_id);
254 if (!thread_id || !process_id) { 302 if (!thread_id || !process_id) {
303 UMA_HISTOGRAM_ENUMERATION(
304 "Chrome.ProcessSingleton.RemoteProcessInteractionResult",
305 REMOTE_PROCESS_NOT_FOUND, MAX_HUNG_REMOTE_PROCESS_ACTION);
255 remote_window_ = NULL; 306 remote_window_ = NULL;
256 return PROCESS_NONE; 307 return PROCESS_NONE;
257 } 308 }
258 309
259 // Get a handle to the process that created the window. 310 // Get a handle to the process that created the window.
260 base::Process process = base::Process::Open(process_id); 311 base::Process process = base::Process::Open(process_id);
261 312
262 // TODO(manzagop): capture a hang report. 313 // TODO(manzagop): capture a hang report.
263 314
264 // Scan for every window to find a visible one. 315 // Scan for every window to find a visible one.
265 bool visible_window = false; 316 bool visible_window = false;
266 ::EnumThreadWindows(thread_id, 317 ::EnumThreadWindows(thread_id,
267 &BrowserWindowEnumeration, 318 &BrowserWindowEnumeration,
268 reinterpret_cast<LPARAM>(&visible_window)); 319 reinterpret_cast<LPARAM>(&visible_window));
269 320
270 // If there is a visible browser window, ask the user before killing it. 321 // If there is a visible browser window, ask the user before killing it.
271 if (visible_window && !should_kill_remote_process_callback_.Run()) { 322 if (visible_window && !should_kill_remote_process_callback_.Run()) {
272 // The user denied. Quit silently. 323 // The user denied. Quit silently.
273 return PROCESS_NOTIFIED; 324 return PROCESS_NOTIFIED;
274 } 325 }
326 UMA_HISTOGRAM_ENUMERATION(
327 "Chrome.ProcessSingleton.RemoteHungProcessTerminateReason",
328 visible_window ? USER_ACCEPTED_TERMINATION : NO_VISIBLE_WINDOW_FOUND,
329 MAX_REMOTE_HUNG_PROCESS_TERMINATE_REASON);
275 330
276 // Time to take action. Kill the browser process. 331 // Time to take action. Kill the browser process.
277 process.Terminate(content::RESULT_CODE_HUNG, true); 332 TerminateProcessWithHistograms(process, content::RESULT_CODE_HUNG);
333
278 remote_window_ = NULL; 334 remote_window_ = NULL;
279 return PROCESS_NONE; 335 return PROCESS_NONE;
280 } 336 }
281 337
282 ProcessSingleton::NotifyResult 338 ProcessSingleton::NotifyResult
283 ProcessSingleton::NotifyOtherProcessOrCreate() { 339 ProcessSingleton::NotifyOtherProcessOrCreate() {
284 const base::TimeTicks begin_ticks = base::TimeTicks::Now(); 340 const base::TimeTicks begin_ticks = base::TimeTicks::Now();
285 for (int i = 0; i < 2; ++i) { 341 for (int i = 0; i < 2; ++i) {
286 if (Create()) { 342 if (Create()) {
287 UMA_HISTOGRAM_MEDIUM_TIMES("Chrome.ProcessSingleton.TimeToCreate", 343 UMA_HISTOGRAM_MEDIUM_TIMES("Chrome.ProcessSingleton.TimeToCreate",
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 return window_.hwnd() != NULL; 427 return window_.hwnd() != NULL;
372 } 428 }
373 429
374 void ProcessSingleton::Cleanup() { 430 void ProcessSingleton::Cleanup() {
375 } 431 }
376 432
377 void ProcessSingleton::OverrideShouldKillRemoteProcessCallbackForTesting( 433 void ProcessSingleton::OverrideShouldKillRemoteProcessCallbackForTesting(
378 const ShouldKillRemoteProcessCallback& display_dialog_callback) { 434 const ShouldKillRemoteProcessCallback& display_dialog_callback) {
379 should_kill_remote_process_callback_ = display_dialog_callback; 435 should_kill_remote_process_callback_ = display_dialog_callback;
380 } 436 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698