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

Side by Side Diff: client/crashpad_client_win.cc

Issue 1287073002: Implement more of CrashpadClient on Windows (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: elseif Created 5 years, 4 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
« no previous file with comments | « client/crashpad_client_mac.cc ('k') | client/crashpad_info.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 2015 The Crashpad Authors. All rights reserved. 1 // Copyright 2015 The Crashpad Authors. All rights reserved.
2 // 2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License. 4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at 5 // You may obtain a copy of the License at
6 // 6 //
7 // http://www.apache.org/licenses/LICENSE-2.0 7 // http://www.apache.org/licenses/LICENSE-2.0
8 // 8 //
9 // Unless required by applicable law or agreed to in writing, software 9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, 10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and 12 // See the License for the specific language governing permissions and
13 // limitations under the License. 13 // limitations under the License.
14 14
15 #include "client/crashpad_client.h" 15 #include "client/crashpad_client.h"
16 16
17 #include <windows.h> 17 #include <windows.h>
18 18
19 #include "base/atomicops.h"
19 #include "base/logging.h" 20 #include "base/logging.h"
21 #include "base/strings/string16.h"
22 #include "base/strings/utf_string_conversions.h"
23 #include "client/crashpad_info.h"
24 #include "client/registration_protocol_win.h"
25 #include "util/file/file_io.h"
26 #include "util/win/scoped_handle.h"
20 27
21 namespace { 28 namespace {
22 // Time to wait for the handler to create a dump. This is tricky to figure out. 29 // Time to wait for the handler to create a dump. This is tricky to figure out.
23 const DWORD kMillisecondsUntilTerminate = 5000; 30 const DWORD kMillisecondsUntilTerminate = 5000;
24 31
25 // This is the exit code that the process will return to the system once the 32 // This is the exit code that the process will return to the system once the
26 // crash has been handled by Crashpad. We don't want to clash with the 33 // crash has been handled by Crashpad. We don't want to clash with the
27 // application-defined exit codes but we don't know them so we use one that is 34 // application-defined exit codes but we don't know them so we use one that is
28 // unlikely to be used. 35 // unlikely to be used.
29 const UINT kCrashExitCode = 0xffff7001; 36 const UINT kCrashExitCode = 0xffff7001;
30 37
31 // These two handles to events are leaked. 38 // These two handles to events are leaked.
32 HANDLE g_signal_exception = nullptr; 39 HANDLE g_signal_exception = nullptr;
33 HANDLE g_wait_termination = nullptr; 40 HANDLE g_wait_termination = nullptr;
34 41
42 // Tracks whether a thread has already entered UnhandledExceptionHandler.
43 base::subtle::AtomicWord g_have_crashed;
44
35 LONG WINAPI UnhandledExceptionHandler(EXCEPTION_POINTERS* exception_pointers) { 45 LONG WINAPI UnhandledExceptionHandler(EXCEPTION_POINTERS* exception_pointers) {
36 // TODO (cpu): Here write |exception_pointers| to g_crashpad_info. 46 // This is a per-process handler. While this handler is being invoked, other
47 // threads are still executing as usual, so multiple threads could enter at
48 // the same time. Because we're in a crashing state, we shouldn't be doing
49 // anything that might cause allocations, call into kernel mode, etc. So, we
50 // don't want to take a critical section here to avoid simultaneous access to
51 // the global exception pointers in CrashpadInfo. Because the crash handler
52 // will record all threads, it's fine to simply have the second and subsequent
53 // entrants block here. They will soon be suspended by the crash handler, and
54 // then the entire process will be terminated below. This means that we won't
55 // save the exception pointers from the second and further crashes, but
56 // contention here is very unlikely, and we'll still have a stack that's
57 // blocked at this location.
58 if (base::subtle::Barrier_AtomicIncrement(&g_have_crashed, 1) > 1) {
59 SleepEx(false, INFINITE);
60 }
61
62 // Otherwise, we're the first thread, so record the exception pointer and
63 // signal the crash handler.
64 crashpad::CrashpadInfo::GetCrashpadInfo()->set_exception_pointers(
65 exception_pointers);
37 DWORD rv = SignalObjectAndWait(g_signal_exception, 66 DWORD rv = SignalObjectAndWait(g_signal_exception,
38 g_wait_termination, 67 g_wait_termination,
39 kMillisecondsUntilTerminate, 68 kMillisecondsUntilTerminate,
40 FALSE); 69 FALSE);
41 if (rv != WAIT_OBJECT_0) { 70 if (rv != WAIT_OBJECT_0) {
42 // Something went wrong. It is likely that a dump has not been created. 71 // Something went wrong. It is likely that a dump has not been created.
43 if (rv == WAIT_TIMEOUT) { 72 if (rv == WAIT_TIMEOUT) {
44 LOG(WARNING) << "SignalObjectAndWait timed out"; 73 LOG(WARNING) << "SignalObjectAndWait timed out";
45 } else { 74 } else {
46 PLOG(WARNING) << "SignalObjectAndWait error"; 75 PLOG(WARNING) << "SignalObjectAndWait error";
47 } 76 }
48 } 77 }
49 // We don't want to generate more exceptions, so we take the fast route. 78 // We don't want to generate more exceptions, so we take the fast route.
50 TerminateProcess(GetCurrentProcess(), kCrashExitCode); 79 TerminateProcess(GetCurrentProcess(), kCrashExitCode);
51 return 0L; 80 return 0L;
52 } 81 }
53 82
83 // Returns a pipe handle connected to the RegistrationServer.
84 crashpad::ScopedFileHANDLE Connect(const base::string16& pipe_name) {
85 crashpad::ScopedFileHANDLE pipe;
86 const int kMaxTries = 5;
87 for (int tries = 0; tries < kMaxTries; ++tries) {
88 pipe.reset(CreateFile(pipe_name.c_str(),
89 GENERIC_READ | GENERIC_WRITE,
90 0,
91 nullptr,
92 OPEN_EXISTING,
93 SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS,
94 nullptr));
95 if (pipe.is_valid())
96 break;
97
98 // If busy, wait 60s before retrying.
99 if (GetLastError() != ERROR_PIPE_BUSY) {
100 PLOG(ERROR) << "CreateFile pipe connection";
101 return crashpad::ScopedFileHANDLE();
102 } else if (!WaitNamedPipe(pipe_name.c_str(), 60000)) {
103 PLOG(ERROR) << "WaitNamedPipe";
104 }
105 }
106
107 if (!pipe.is_valid())
108 return crashpad::ScopedFileHANDLE();
109
110 DWORD mode = PIPE_READMODE_MESSAGE;
111 if (!SetNamedPipeHandleState(pipe.get(),
112 &mode,
113 nullptr, // Don't set maximum bytes.
114 nullptr)) { // Don't set maximum time.
115 PLOG(ERROR) << "SetNamedPipeHandleState";
116 return crashpad::ScopedFileHANDLE();
117 }
118
119 return pipe.Pass();
120 }
121
54 } // namespace 122 } // namespace
55 123
56 namespace crashpad { 124 namespace crashpad {
57 125
58 CrashpadClient::CrashpadClient() { 126 CrashpadClient::CrashpadClient() {
59 } 127 }
60 128
61 CrashpadClient::~CrashpadClient() { 129 CrashpadClient::~CrashpadClient() {
62 } 130 }
63 131
64 bool CrashpadClient::StartHandler( 132 bool CrashpadClient::StartHandler(
65 const base::FilePath& handler, 133 const base::FilePath& handler,
66 const base::FilePath& database, 134 const base::FilePath& database,
67 const std::string& url, 135 const std::string& url,
68 const std::map<std::string, std::string>& annotations, 136 const std::map<std::string, std::string>& annotations,
69 const std::vector<std::string>& arguments) { 137 const std::vector<std::string>& arguments) {
70 // TODO(cpu): Provide a reference implementation.
71 return false; 138 return false;
72 } 139 }
73 140
74 bool CrashpadClient::SetHandler(const std::string& ipc_port) { 141 bool CrashpadClient::SetHandler(const std::string& ipc_port) {
75 // TODO (cpu): Contact the handler and obtain g_signal_exception and 142 RegistrationRequest request = {0};
76 // g_wait_termination. 143 request.client_process_id = GetCurrentProcessId();
77 return false; 144 request.crashpad_info_address =
145 reinterpret_cast<WinVMAddress>(CrashpadInfo::GetCrashpadInfo());
146
147 RegistrationResponse response = {0};
148
149 ScopedFileHANDLE pipe = Connect(base::UTF8ToUTF16(ipc_port));
150 if (!pipe.is_valid())
151 return false;
152 bool result = LoggingWriteFile(pipe.get(), &request, sizeof(request)) &&
153 LoggingReadFile(pipe.get(), &response, sizeof(response));
154 if (!result)
155 return result;
156
157 // The server returns these already duplicated to be valid in this process.
158 g_signal_exception = reinterpret_cast<HANDLE>(response.request_report_event);
159 g_wait_termination =
160 reinterpret_cast<HANDLE>(response.report_complete_event);
161 return true;
78 } 162 }
79 163
80 bool CrashpadClient::UseHandler() { 164 bool CrashpadClient::UseHandler() {
81 if (!g_signal_exception) 165 if (!g_signal_exception)
82 return false; 166 return false;
83 if (!g_wait_termination) 167 if (!g_wait_termination)
84 return false; 168 return false;
85 // In theory we could store the previous handler but it is not clear what 169 // In theory we could store the previous handler but it is not clear what
86 // use we have for it. 170 // use we have for it.
87 SetUnhandledExceptionFilter(&UnhandledExceptionHandler); 171 SetUnhandledExceptionFilter(&UnhandledExceptionHandler);
88 return true; 172 return true;
89 } 173 }
90 174
91 } // namespace crashpad 175 } // namespace crashpad
OLDNEW
« no previous file with comments | « client/crashpad_client_mac.cc ('k') | client/crashpad_info.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698