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 |