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

Side by Side Diff: util/win/exception_handler_server.cc

Issue 1356383002: win: Implement CRASHPAD_SIMULATE_CRASH() (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: fixes Created 5 years, 2 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 | « util/win/exception_handler_server.h ('k') | util/win/registration_protocol_win.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,
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 //! \brief The context data for registered threadpool waits. 96 //! \brief The context data for registered threadpool waits.
97 //! 97 //!
98 //! This object must be created and destroyed on the main thread. Access must be 98 //! This object must be created and destroyed on the main thread. Access must be
99 //! guarded by use of the lock() with the exception of the threadpool wait 99 //! guarded by use of the lock() with the exception of the threadpool wait
100 //! variables which are accessed only by the main thread. 100 //! variables which are accessed only by the main thread.
101 class ClientData { 101 class ClientData {
102 public: 102 public:
103 ClientData(HANDLE port, 103 ClientData(HANDLE port,
104 ExceptionHandlerServer::Delegate* delegate, 104 ExceptionHandlerServer::Delegate* delegate,
105 ScopedKernelHANDLE process, 105 ScopedKernelHANDLE process,
106 WinVMAddress exception_information_address, 106 WinVMAddress crash_exception_information_address,
107 WAITORTIMERCALLBACK dump_request_callback, 107 WinVMAddress non_crash_exception_information_address,
108 WAITORTIMERCALLBACK crash_dump_request_callback,
109 WAITORTIMERCALLBACK non_crash_dump_request_callback,
108 WAITORTIMERCALLBACK process_end_callback) 110 WAITORTIMERCALLBACK process_end_callback)
109 : dump_request_thread_pool_wait_(INVALID_HANDLE_VALUE), 111 : crash_dump_request_thread_pool_wait_(INVALID_HANDLE_VALUE),
112 non_crash_dump_request_thread_pool_wait_(INVALID_HANDLE_VALUE),
110 process_end_thread_pool_wait_(INVALID_HANDLE_VALUE), 113 process_end_thread_pool_wait_(INVALID_HANDLE_VALUE),
111 lock_(), 114 lock_(),
112 port_(port), 115 port_(port),
113 delegate_(delegate), 116 delegate_(delegate),
114 dump_requested_event_( 117 crash_dump_requested_event_(
118 CreateEvent(nullptr, false /* auto reset */, false, nullptr)),
119 non_crash_dump_requested_event_(
120 CreateEvent(nullptr, false /* auto reset */, false, nullptr)),
121 non_crash_dump_completed_event_(
115 CreateEvent(nullptr, false /* auto reset */, false, nullptr)), 122 CreateEvent(nullptr, false /* auto reset */, false, nullptr)),
116 process_(process.Pass()), 123 process_(process.Pass()),
117 exception_information_address_(exception_information_address) { 124 crash_exception_information_address_(
118 RegisterThreadPoolWaits(dump_request_callback, process_end_callback); 125 crash_exception_information_address),
126 non_crash_exception_information_address_(
127 non_crash_exception_information_address) {
128 RegisterThreadPoolWaits(crash_dump_request_callback,
129 non_crash_dump_request_callback,
130 process_end_callback);
119 } 131 }
120 132
121 ~ClientData() { 133 ~ClientData() {
122 // It is important that this only access the threadpool waits (it's called 134 // It is important that this only access the threadpool waits (it's called
123 // from the main thread) until the waits are unregistered, to ensure that 135 // from the main thread) until the waits are unregistered, to ensure that
124 // any outstanding callbacks are complete. 136 // any outstanding callbacks are complete.
125 UnregisterThreadPoolWaits(); 137 UnregisterThreadPoolWaits();
126 } 138 }
127 139
128 base::Lock* lock() { return &lock_; } 140 base::Lock* lock() { return &lock_; }
129 HANDLE port() const { return port_; } 141 HANDLE port() const { return port_; }
130 ExceptionHandlerServer::Delegate* delegate() const { return delegate_; } 142 ExceptionHandlerServer::Delegate* delegate() const { return delegate_; }
131 HANDLE dump_requested_event() const { return dump_requested_event_.get(); } 143 HANDLE crash_dump_requested_event() const {
132 WinVMAddress exception_information_address() const { 144 return crash_dump_requested_event_.get();
133 return exception_information_address_; 145 }
146 HANDLE non_crash_dump_requested_event() const {
147 return non_crash_dump_requested_event_.get();
148 }
149 HANDLE non_crash_dump_completed_event() const {
150 return non_crash_dump_completed_event_.get();
151 }
152 WinVMAddress crash_exception_information_address() const {
153 return crash_exception_information_address_;
154 }
155 WinVMAddress non_crash_exception_information_address() const {
156 return non_crash_exception_information_address_;
134 } 157 }
135 HANDLE process() const { return process_.get(); } 158 HANDLE process() const { return process_.get(); }
136 159
137 private: 160 private:
138 void RegisterThreadPoolWaits(WAITORTIMERCALLBACK dump_request_callback, 161 void RegisterThreadPoolWaits(
139 WAITORTIMERCALLBACK process_end_callback) { 162 WAITORTIMERCALLBACK crash_dump_request_callback,
140 if (!RegisterWaitForSingleObject(&dump_request_thread_pool_wait_, 163 WAITORTIMERCALLBACK non_crash_dump_request_callback,
141 dump_requested_event_.get(), 164 WAITORTIMERCALLBACK process_end_callback) {
142 dump_request_callback, 165 if (!RegisterWaitForSingleObject(&crash_dump_request_thread_pool_wait_,
166 crash_dump_requested_event_.get(),
167 crash_dump_request_callback,
143 this, 168 this,
144 INFINITE, 169 INFINITE,
145 WT_EXECUTEDEFAULT)) { 170 WT_EXECUTEDEFAULT)) {
146 LOG(ERROR) << "RegisterWaitForSingleObject dump requested"; 171 LOG(ERROR) << "RegisterWaitForSingleObject crash dump requested";
172 }
173
174 if (!RegisterWaitForSingleObject(&non_crash_dump_request_thread_pool_wait_,
175 non_crash_dump_requested_event_.get(),
176 non_crash_dump_request_callback,
177 this,
178 INFINITE,
179 WT_EXECUTEDEFAULT)) {
180 LOG(ERROR) << "RegisterWaitForSingleObject non-crash dump requested";
147 } 181 }
148 182
149 if (!RegisterWaitForSingleObject(&process_end_thread_pool_wait_, 183 if (!RegisterWaitForSingleObject(&process_end_thread_pool_wait_,
150 process_.get(), 184 process_.get(),
151 process_end_callback, 185 process_end_callback,
152 this, 186 this,
153 INFINITE, 187 INFINITE,
154 WT_EXECUTEONLYONCE)) { 188 WT_EXECUTEONLYONCE)) {
155 LOG(ERROR) << "RegisterWaitForSingleObject process end"; 189 LOG(ERROR) << "RegisterWaitForSingleObject process end";
156 } 190 }
157 } 191 }
158 192
159 // This blocks until outstanding calls complete so that we know it's safe to 193 // This blocks until outstanding calls complete so that we know it's safe to
160 // delete this object. Because of this, it must be executed on the main 194 // delete this object. Because of this, it must be executed on the main
161 // thread, not a threadpool thread. 195 // thread, not a threadpool thread.
162 void UnregisterThreadPoolWaits() { 196 void UnregisterThreadPoolWaits() {
163 UnregisterWaitEx(dump_request_thread_pool_wait_, INVALID_HANDLE_VALUE); 197 UnregisterWaitEx(crash_dump_request_thread_pool_wait_,
164 dump_request_thread_pool_wait_ = INVALID_HANDLE_VALUE; 198 INVALID_HANDLE_VALUE);
199 crash_dump_request_thread_pool_wait_ = INVALID_HANDLE_VALUE;
200 UnregisterWaitEx(non_crash_dump_request_thread_pool_wait_,
201 INVALID_HANDLE_VALUE);
202 non_crash_dump_request_thread_pool_wait_ = INVALID_HANDLE_VALUE;
165 UnregisterWaitEx(process_end_thread_pool_wait_, INVALID_HANDLE_VALUE); 203 UnregisterWaitEx(process_end_thread_pool_wait_, INVALID_HANDLE_VALUE);
166 process_end_thread_pool_wait_ = INVALID_HANDLE_VALUE; 204 process_end_thread_pool_wait_ = INVALID_HANDLE_VALUE;
167 } 205 }
168 206
169 // These are only accessed on the main thread. 207 // These are only accessed on the main thread.
170 HANDLE dump_request_thread_pool_wait_; 208 HANDLE crash_dump_request_thread_pool_wait_;
209 HANDLE non_crash_dump_request_thread_pool_wait_;
171 HANDLE process_end_thread_pool_wait_; 210 HANDLE process_end_thread_pool_wait_;
172 211
173 base::Lock lock_; 212 base::Lock lock_;
174 // Access to these fields must be guarded by lock_. 213 // Access to these fields must be guarded by lock_.
175 HANDLE port_; // weak 214 HANDLE port_; // weak
176 ExceptionHandlerServer::Delegate* delegate_; // weak 215 ExceptionHandlerServer::Delegate* delegate_; // weak
177 ScopedKernelHANDLE dump_requested_event_; 216 ScopedKernelHANDLE crash_dump_requested_event_;
217 ScopedKernelHANDLE non_crash_dump_requested_event_;
218 ScopedKernelHANDLE non_crash_dump_completed_event_;
178 ScopedKernelHANDLE process_; 219 ScopedKernelHANDLE process_;
179 WinVMAddress exception_information_address_; 220 WinVMAddress crash_exception_information_address_;
221 WinVMAddress non_crash_exception_information_address_;
180 222
181 DISALLOW_COPY_AND_ASSIGN(ClientData); 223 DISALLOW_COPY_AND_ASSIGN(ClientData);
182 }; 224 };
183 225
184 } // namespace internal 226 } // namespace internal
185 227
186 ExceptionHandlerServer::Delegate::~Delegate() { 228 ExceptionHandlerServer::Delegate::~Delegate() {
187 } 229 }
188 230
189 ExceptionHandlerServer::ExceptionHandlerServer() 231 ExceptionHandlerServer::ExceptionHandlerServer()
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
357 PCHECK(RevertToSelf()); 399 PCHECK(RevertToSelf());
358 if (!client_process) { 400 if (!client_process) {
359 LOG(ERROR) << "failed to open " << message.registration.client_process_id; 401 LOG(ERROR) << "failed to open " << message.registration.client_process_id;
360 return false; 402 return false;
361 } 403 }
362 } 404 }
363 405
364 internal::ClientData* client; 406 internal::ClientData* client;
365 { 407 {
366 base::AutoLock lock(*service_context.clients_lock()); 408 base::AutoLock lock(*service_context.clients_lock());
367 client = 409 client = new internal::ClientData(
368 new internal::ClientData(service_context.port(), 410 service_context.port(),
369 service_context.delegate(), 411 service_context.delegate(),
370 ScopedKernelHANDLE(client_process), 412 ScopedKernelHANDLE(client_process),
371 message.registration.exception_information, 413 message.registration.crash_exception_information,
372 &OnDumpEvent, 414 message.registration.non_crash_exception_information,
373 &OnProcessEnd); 415 &OnCrashDumpEvent,
416 &OnNonCrashDumpEvent,
417 &OnProcessEnd);
374 service_context.clients()->insert(client); 418 service_context.clients()->insert(client);
375 } 419 }
376 420
377 // Duplicate the events back to the client so they can request a dump. 421 // Duplicate the events back to the client so they can request a dump.
378 ServerToClientMessage response; 422 ServerToClientMessage response;
379 response.registration.request_report_event = 423 response.registration.request_crash_dump_event =
380 base::checked_cast<uint32_t>(reinterpret_cast<uintptr_t>( 424 base::checked_cast<uint32_t>(reinterpret_cast<uintptr_t>(DuplicateEvent(
381 DuplicateEvent(client->process(), client->dump_requested_event()))); 425 client->process(), client->crash_dump_requested_event())));
426 response.registration.request_non_crash_dump_event =
427 base::checked_cast<uint32_t>(reinterpret_cast<uintptr_t>(DuplicateEvent(
428 client->process(), client->non_crash_dump_requested_event())));
429 response.registration.non_crash_dump_completed_event =
430 base::checked_cast<uint32_t>(reinterpret_cast<uintptr_t>(DuplicateEvent(
431 client->process(), client->non_crash_dump_completed_event())));
382 432
383 if (!LoggingWriteFile(service_context.pipe(), &response, sizeof(response))) 433 if (!LoggingWriteFile(service_context.pipe(), &response, sizeof(response)))
384 return false; 434 return false;
385 435
386 return false; 436 return false;
387 } 437 }
388 438
389 // static 439 // static
390 DWORD __stdcall ExceptionHandlerServer::PipeServiceProc(void* ctx) { 440 DWORD __stdcall ExceptionHandlerServer::PipeServiceProc(void* ctx) {
391 internal::PipeServiceContext* service_context = 441 internal::PipeServiceContext* service_context =
392 reinterpret_cast<internal::PipeServiceContext*>(ctx); 442 reinterpret_cast<internal::PipeServiceContext*>(ctx);
393 DCHECK(service_context); 443 DCHECK(service_context);
394 444
395 for (;;) { 445 for (;;) {
396 bool ret = ConnectNamedPipe(service_context->pipe(), nullptr); 446 bool ret = ConnectNamedPipe(service_context->pipe(), nullptr);
397 if (!ret && GetLastError() != ERROR_PIPE_CONNECTED) { 447 if (!ret && GetLastError() != ERROR_PIPE_CONNECTED) {
398 PLOG(ERROR) << "ConnectNamedPipe"; 448 PLOG(ERROR) << "ConnectNamedPipe";
399 } else if (ServiceClientConnection(*service_context)) { 449 } else if (ServiceClientConnection(*service_context)) {
400 break; 450 break;
401 } 451 }
402 DisconnectNamedPipe(service_context->pipe()); 452 DisconnectNamedPipe(service_context->pipe());
403 } 453 }
404 454
405 delete service_context; 455 delete service_context;
406 456
407 return 0; 457 return 0;
408 } 458 }
409 459
410 // static 460 // static
411 void __stdcall ExceptionHandlerServer::OnDumpEvent(void* ctx, BOOLEAN) { 461 void __stdcall ExceptionHandlerServer::OnCrashDumpEvent(void* ctx, BOOLEAN) {
412 // This function is executed on the thread pool. 462 // This function is executed on the thread pool.
413 internal::ClientData* client = reinterpret_cast<internal::ClientData*>(ctx); 463 internal::ClientData* client = reinterpret_cast<internal::ClientData*>(ctx);
414 base::AutoLock lock(*client->lock()); 464 base::AutoLock lock(*client->lock());
415 465
416 // Capture the exception. 466 // Capture the exception.
417 unsigned int exit_code = client->delegate()->ExceptionHandlerServerException( 467 unsigned int exit_code = client->delegate()->ExceptionHandlerServerException(
418 client->process(), client->exception_information_address()); 468 client->process(), client->crash_exception_information_address());
419 469
420 TerminateProcess(client->process(), exit_code); 470 TerminateProcess(client->process(), exit_code);
421 } 471 }
422 472
423 // static 473 // static
474 void __stdcall ExceptionHandlerServer::OnNonCrashDumpEvent(void* ctx, BOOLEAN) {
475 // This function is executed on the thread pool.
476 internal::ClientData* client = reinterpret_cast<internal::ClientData*>(ctx);
477 base::AutoLock lock(*client->lock());
478
479 // Capture the exception.
480 client->delegate()->ExceptionHandlerServerException(
481 client->process(), client->non_crash_exception_information_address());
482
483 bool result = SetEvent(client->non_crash_dump_completed_event());
484 PLOG_IF(ERROR, !result) << "SetEvent";
485 }
486
487 // static
424 void __stdcall ExceptionHandlerServer::OnProcessEnd(void* ctx, BOOLEAN) { 488 void __stdcall ExceptionHandlerServer::OnProcessEnd(void* ctx, BOOLEAN) {
425 // This function is executed on the thread pool. 489 // This function is executed on the thread pool.
426 internal::ClientData* client = reinterpret_cast<internal::ClientData*>(ctx); 490 internal::ClientData* client = reinterpret_cast<internal::ClientData*>(ctx);
427 base::AutoLock lock(*client->lock()); 491 base::AutoLock lock(*client->lock());
428 492
429 // Post back to the main thread to have it delete this client record. 493 // Post back to the main thread to have it delete this client record.
430 PostQueuedCompletionStatus(client->port(), 0, ULONG_PTR(client), nullptr); 494 PostQueuedCompletionStatus(client->port(), 0, ULONG_PTR(client), nullptr);
431 } 495 }
432 496
433 } // namespace crashpad 497 } // namespace crashpad
OLDNEW
« no previous file with comments | « util/win/exception_handler_server.h ('k') | util/win/registration_protocol_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698