Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
|
scottmg
2017/01/06 18:29:04
2017
Sigurður Ásgeirsson
2017/01/06 20:59:10
Done.
| |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "components/crash/content/app/fallback_crash_handler_launcher_win.h" | |
| 6 | |
| 7 #include "base/logging.h" | |
| 8 #include "base/strings/string_number_conversions.h" | |
| 9 #include "base/win/win_util.h" | |
| 10 | |
| 11 namespace crash_reporter { | |
| 12 | |
| 13 FallbackCrashHandlerLauncher::FallbackCrashHandlerLauncher() { | |
| 14 memset(&exception_pointers_, 0, sizeof(exception_pointers_)); | |
| 15 } | |
| 16 | |
| 17 FallbackCrashHandlerLauncher::~FallbackCrashHandlerLauncher() {} | |
| 18 | |
| 19 bool FallbackCrashHandlerLauncher::Initialize( | |
| 20 const base::CommandLine& program, | |
| 21 const base::FilePath& crashpad_database) { | |
| 22 // Open an inheritable handle to self. This will be inherited to the handler. | |
| 23 DWORD kAccessMask = | |
|
scottmg
2017/01/06 18:29:04
const DWORD if using k..., otherwise access_mask.
Sigurður Ásgeirsson
2017/01/06 20:59:10
Done.
| |
| 24 PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_DUP_HANDLE; | |
| 25 self_process_handle_.Set( | |
| 26 OpenProcess(kAccessMask, TRUE, ::GetCurrentProcessId())); | |
| 27 if (!self_process_handle_.IsValid()) | |
| 28 return false; | |
| 29 | |
| 30 // Setup the startup info for inheriting the self process handle into the | |
| 31 // fallback crash handler. | |
| 32 if (!startup_info_.InitializeProcThreadAttributeList(1)) | |
| 33 return false; | |
| 34 | |
| 35 HANDLE raw_self_process_handle = self_process_handle_.Get(); | |
| 36 if (!startup_info_.UpdateProcThreadAttribute( | |
| 37 PROC_THREAD_ATTRIBUTE_HANDLE_LIST, &raw_self_process_handle, | |
| 38 sizeof(raw_self_process_handle))) { | |
| 39 return false; | |
| 40 } | |
| 41 | |
| 42 // Build the command line from a copy of the command line passed in. | |
| 43 base::CommandLine cmd_line(program); | |
| 44 cmd_line.AppendSwitchPath("database", crashpad_database); | |
| 45 cmd_line.AppendSwitchASCII( | |
| 46 "exception-pointers", | |
| 47 base::UintToString(reinterpret_cast<uintptr_t>(&exception_pointers_))); | |
| 48 cmd_line.AppendSwitchASCII( | |
| 49 "process", base::UintToString( | |
| 50 base::win::HandleToUint32(self_process_handle_.Get()))); | |
| 51 | |
| 52 std::wstring str_cmd_line = cmd_line.GetCommandLineString(); | |
| 53 | |
| 54 // Append the for now abortive thread argument manually. | |
| 55 str_cmd_line.append(L" --thread="); | |
| 56 | |
| 57 // Store the command line string for easy use later. | |
| 58 cmd_line_.assign(str_cmd_line.begin(), str_cmd_line.end()); | |
| 59 | |
| 60 // Reserve space for appending the thread id later at crash time, without | |
| 61 // requiring an allocation to happen. | |
| 62 cmd_line_.reserve(cmd_line_.size() + 32); | |
| 63 | |
| 64 return true; | |
| 65 } | |
| 66 | |
| 67 DWORD FallbackCrashHandlerLauncher::LaunchAndWaitForHandler( | |
| 68 EXCEPTION_POINTERS* exception_pointers) { | |
| 69 DCHECK(!cmd_line_.empty()); | |
| 70 DCHECK_EQ('=', cmd_line_.back()); | |
| 71 // This program has crashed. Try and not use anything but the stack. | |
| 72 | |
| 73 // Append the current thread's ID to the command line, without incurring | |
| 74 // an allocation. | |
| 75 wchar_t buf[32]; | |
| 76 int len = wsprintf(buf, L"%d", GetCurrentThreadId()); | |
|
scottmg
2017/01/06 18:29:04
How about doing a resize() in Initialize() and the
Sigurður Ásgeirsson
2017/01/06 20:59:10
Good idea, done!
| |
| 77 // Append the thread ID and the terminating zero to the command line string. | |
| 78 cmd_line_.insert(cmd_line_.end(), buf, buf + len + 1); | |
| 79 | |
| 80 // Copy the exception pointers to our member variable, whose address is | |
| 81 // already baked into the command line. | |
| 82 exception_pointers_ = *exception_pointers; | |
| 83 | |
| 84 // Launch the pre-cooked command line. | |
| 85 DWORD error = ERROR_SUCCESS; | |
| 86 PROCESS_INFORMATION process_info = {}; | |
| 87 if (!CreateProcess(nullptr, // Application name. | |
| 88 &cmd_line_[0], // Command line. | |
| 89 nullptr, // Process attributes. | |
| 90 nullptr, // Thread attributes. | |
| 91 true, // Inherit handles. | |
| 92 0, // Creation flags. | |
| 93 nullptr, // Environment. | |
| 94 nullptr, // Current directory. | |
| 95 startup_info_.startup_info(), // Startup info. | |
| 96 &process_info)) { | |
| 97 error = GetLastError(); | |
|
scottmg
2017/01/06 18:29:04
return GetLastError() seems simpler here, and move
Sigurður Ásgeirsson
2017/01/06 20:59:10
Done.
| |
| 98 return error; | |
| 99 } | |
| 100 | |
| 101 // Wait on the fallback crash handler process. The expectation is that this | |
| 102 // will never return, as the fallback crash handler will terminate this | |
| 103 // process. For testing, and full-on belt and suspenders, cover for this | |
| 104 // returning. | |
| 105 error = WaitForSingleObject(process_info.hProcess, INFINITE); | |
| 106 if (error != WAIT_OBJECT_0) { | |
|
scottmg
2017/01/06 18:29:04
Please add (or add a note to add) UMA that tracks
Sigurður Ásgeirsson
2017/01/06 20:59:10
Added a TODO - maybe it'll be saner to do this fro
| |
| 107 // This should never happen, barring handle abuse. | |
| 108 NOTREACHED(); | |
| 109 error = GetLastError(); | |
| 110 } else { | |
| 111 // On successful wait, return the exit code of the fallback crash handler | |
| 112 // process. | |
| 113 if (!GetExitCodeProcess(process_info.hProcess, &error)) { | |
| 114 // This should never happen, barring handle abuse. | |
| 115 NOTREACHED(); | |
| 116 error = GetLastError(); | |
| 117 } | |
| 118 } | |
| 119 | |
| 120 // Close the handles returned from CreateProcess. | |
| 121 CloseHandle(process_info.hProcess); | |
| 122 CloseHandle(process_info.hThread); | |
| 123 | |
| 124 return error; | |
| 125 } | |
| 126 | |
| 127 } // namespace crash_reporter | |
| OLD | NEW |