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

Side by Side Diff: base/process_util_win.cc

Issue 5172009: This adds some plumbing for propagating the reason for a renderer's death (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Final review changes Created 10 years 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
« no previous file with comments | « base/process_util_unittest.cc ('k') | chrome/browser/browser_child_process_host.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 "base/process_util.h" 5 #include "base/process_util.h"
6 6
7 #include <fcntl.h> 7 #include <fcntl.h>
8 #include <io.h> 8 #include <io.h>
9 #include <windows.h> 9 #include <windows.h>
10 #include <userenv.h> 10 #include <userenv.h>
(...skipping 12 matching lines...) Expand all
23 // userenv.dll is required for CreateEnvironmentBlock(). 23 // userenv.dll is required for CreateEnvironmentBlock().
24 #pragma comment(lib, "userenv.lib") 24 #pragma comment(lib, "userenv.lib")
25 25
26 namespace base { 26 namespace base {
27 27
28 namespace { 28 namespace {
29 29
30 // System pagesize. This value remains constant on x86/64 architectures. 30 // System pagesize. This value remains constant on x86/64 architectures.
31 const int PAGESIZE_KB = 4; 31 const int PAGESIZE_KB = 4;
32 32
33 // Exit codes with special meanings on Windows.
34 const DWORD kNormalTerminationExitCode = 0;
35 const DWORD kDebuggerInactiveExitCode = 0xC0000354;
36 const DWORD kKeyboardInterruptExitCode = 0xC000013A;
37 const DWORD kDebuggerTerminatedExitCode = 0x40010004;
38
39 // This exit code is used by the Windows task manager when it kills a
40 // process. It's value is obviously not that unique, and it's
41 // surprising to me that the task manager uses this value, but it
42 // seems to be common practice on Windows to test for it as an
43 // indication that the task manager has killed something if the
44 // process goes away.
45 const DWORD kProcessKilledExitCode = 1;
46
33 // HeapSetInformation function pointer. 47 // HeapSetInformation function pointer.
34 typedef BOOL (WINAPI* HeapSetFn)(HANDLE, HEAP_INFORMATION_CLASS, PVOID, SIZE_T); 48 typedef BOOL (WINAPI* HeapSetFn)(HANDLE, HEAP_INFORMATION_CLASS, PVOID, SIZE_T);
35 49
36 // Previous unhandled filter. Will be called if not NULL when we intercept an 50 // Previous unhandled filter. Will be called if not NULL when we intercept an
37 // exception. Only used in unit tests. 51 // exception. Only used in unit tests.
38 LPTOP_LEVEL_EXCEPTION_FILTER g_previous_filter = NULL; 52 LPTOP_LEVEL_EXCEPTION_FILTER g_previous_filter = NULL;
39 53
40 // Prints the exception call stack. 54 // Prints the exception call stack.
41 // This is the unit tests exception filter. 55 // This is the unit tests exception filter.
42 long WINAPI StackDumpExceptionFilter(EXCEPTION_POINTERS* info) { 56 long WINAPI StackDumpExceptionFilter(EXCEPTION_POINTERS* info) {
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 112
99 if (result == INVALID_HANDLE_VALUE) 113 if (result == INVALID_HANDLE_VALUE)
100 return false; 114 return false;
101 115
102 *handle = result; 116 *handle = result;
103 return true; 117 return true;
104 } 118 }
105 119
106 bool OpenPrivilegedProcessHandle(ProcessId pid, ProcessHandle* handle) { 120 bool OpenPrivilegedProcessHandle(ProcessId pid, ProcessHandle* handle) {
107 ProcessHandle result = OpenProcess(PROCESS_DUP_HANDLE | 121 ProcessHandle result = OpenProcess(PROCESS_DUP_HANDLE |
108 PROCESS_TERMINATE | 122 PROCESS_TERMINATE |
109 PROCESS_QUERY_INFORMATION | 123 PROCESS_QUERY_INFORMATION |
110 PROCESS_VM_READ | 124 PROCESS_VM_READ |
111 SYNCHRONIZE, 125 SYNCHRONIZE,
112 FALSE, pid); 126 FALSE, pid);
113 127
114 if (result == INVALID_HANDLE_VALUE) 128 if (result == INVALID_HANDLE_VALUE)
115 return false; 129 return false;
116 130
117 *handle = result; 131 *handle = result;
118 return true; 132 return true;
119 } 133 }
120 134
121 bool OpenProcessHandleWithAccess(ProcessId pid, 135 bool OpenProcessHandleWithAccess(ProcessId pid,
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 if (result && wait) { 401 if (result && wait) {
388 // The process may not end immediately due to pending I/O 402 // The process may not end immediately due to pending I/O
389 if (WAIT_OBJECT_0 != WaitForSingleObject(process, 60 * 1000)) 403 if (WAIT_OBJECT_0 != WaitForSingleObject(process, 60 * 1000))
390 DLOG(ERROR) << "Error waiting for process exit: " << GetLastError(); 404 DLOG(ERROR) << "Error waiting for process exit: " << GetLastError();
391 } else if (!result) { 405 } else if (!result) {
392 DLOG(ERROR) << "Unable to terminate process: " << GetLastError(); 406 DLOG(ERROR) << "Unable to terminate process: " << GetLastError();
393 } 407 }
394 return result; 408 return result;
395 } 409 }
396 410
397 bool DidProcessCrash(bool* child_exited, ProcessHandle handle) { 411 TerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code) {
398 DWORD exitcode = 0; 412 DWORD tmp_exit_code = 0;
399 413
400 if (!::GetExitCodeProcess(handle, &exitcode)) { 414 if (!::GetExitCodeProcess(handle, &tmp_exit_code)) {
401 NOTREACHED(); 415 NOTREACHED();
402 // Assume the child has exited. 416 if (exit_code) {
403 if (child_exited) 417 // This really is a random number. We haven't received any
404 *child_exited = true; 418 // information about the exit code, presumably because this
405 return false; 419 // process doesn't have permission to get the exit code, or
420 // because of some other cause for GetExitCodeProcess to fail
421 // (MSDN docs don't give the possible failure error codes for
422 // this function, so it could be anything). But we don't want
423 // to leave exit_code uninitialized, since that could cause
424 // random interpretations of the exit code. So we assume it
425 // terminated "normally" in this case.
426 *exit_code = kNormalTerminationExitCode;
427 }
428 // Assume the child has exited normally if we can't get the exit
429 // code.
430 return TERMINATION_STATUS_NORMAL_TERMINATION;
406 } 431 }
407 if (exitcode == STILL_ACTIVE) { 432 if (tmp_exit_code == STILL_ACTIVE) {
408 DWORD wait_result = WaitForSingleObject(handle, 0); 433 DWORD wait_result = WaitForSingleObject(handle, 0);
409 if (wait_result == WAIT_TIMEOUT) { 434 if (wait_result == WAIT_TIMEOUT) {
410 if (child_exited) 435 if (exit_code)
411 *child_exited = false; 436 *exit_code = wait_result;
412 return false; 437 return TERMINATION_STATUS_STILL_RUNNING;
413 } 438 }
414 439
415 DCHECK_EQ(WAIT_OBJECT_0, wait_result); 440 DCHECK_EQ(WAIT_OBJECT_0, wait_result);
416 441
417 // Strange, the process used 0x103 (STILL_ACTIVE) as exit code. 442 // Strange, the process used 0x103 (STILL_ACTIVE) as exit code.
418 NOTREACHED(); 443 NOTREACHED();
419 444
420 return false; 445 return TERMINATION_STATUS_ABNORMAL_TERMINATION;
421 } 446 }
422 447
423 // We're sure the child has exited. 448 if (exit_code)
424 if (child_exited) 449 *exit_code = tmp_exit_code;
425 *child_exited = true;
426 450
427 // Warning, this is not generic code; it heavily depends on the way 451 switch (tmp_exit_code) {
428 // the rest of the code kills a process. 452 case kNormalTerminationExitCode:
429 453 return TERMINATION_STATUS_NORMAL_TERMINATION;
430 if (exitcode == PROCESS_END_NORMAL_TERMINATION || 454 case kDebuggerInactiveExitCode: // STATUS_DEBUGGER_INACTIVE.
431 exitcode == PROCESS_END_KILLED_BY_USER || 455 case kKeyboardInterruptExitCode: // Control-C/end session.
432 exitcode == PROCESS_END_PROCESS_WAS_HUNG || 456 case kDebuggerTerminatedExitCode: // Debugger terminated process.
433 exitcode == 0xC0000354 || // STATUS_DEBUGGER_INACTIVE. 457 case kProcessKilledExitCode: // Task manager kill.
434 exitcode == 0xC000013A || // Control-C/end session. 458 return TERMINATION_STATUS_PROCESS_WAS_KILLED;
435 exitcode == 0x40010004) { // Debugger terminated process/end session. 459 default:
436 return false; 460 // All other exit codes indicate crashes.
461 return TERMINATION_STATUS_PROCESS_CRASHED;
437 } 462 }
438
439 // All other exit codes indicate crashes.
440 return true;
441 } 463 }
442 464
443 bool WaitForExitCode(ProcessHandle handle, int* exit_code) { 465 bool WaitForExitCode(ProcessHandle handle, int* exit_code) {
444 bool success = WaitForExitCodeWithTimeout(handle, exit_code, INFINITE); 466 bool success = WaitForExitCodeWithTimeout(handle, exit_code, INFINITE);
445 if (!success) 467 if (!success)
446 CloseProcessHandle(handle); 468 CloseProcessHandle(handle);
447 return success; 469 return success;
448 } 470 }
449 471
450 bool WaitForExitCodeWithTimeout(ProcessHandle handle, int* exit_code, 472 bool WaitForExitCodeWithTimeout(ProcessHandle handle, int* exit_code,
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after
887 909
888 PERFORMANCE_INFORMATION info; 910 PERFORMANCE_INFORMATION info;
889 if (!InternalGetPerformanceInfo(&info, sizeof(info))) { 911 if (!InternalGetPerformanceInfo(&info, sizeof(info))) {
890 LOG(ERROR) << "Failed to fetch internal performance info."; 912 LOG(ERROR) << "Failed to fetch internal performance info.";
891 return 0; 913 return 0;
892 } 914 }
893 return (info.CommitTotal * system_info.dwPageSize) / 1024; 915 return (info.CommitTotal * system_info.dwPageSize) / 1024;
894 } 916 }
895 917
896 } // namespace base 918 } // namespace base
OLDNEW
« no previous file with comments | « base/process_util_unittest.cc ('k') | chrome/browser/browser_child_process_host.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698