OLD | NEW |
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 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 crash_exception_information_address, | 106 WinVMAddress crash_exception_information_address, |
107 WinVMAddress non_crash_exception_information_address, | 107 WinVMAddress non_crash_exception_information_address, |
| 108 WinVMAddress debug_critical_section_address, |
108 WAITORTIMERCALLBACK crash_dump_request_callback, | 109 WAITORTIMERCALLBACK crash_dump_request_callback, |
109 WAITORTIMERCALLBACK non_crash_dump_request_callback, | 110 WAITORTIMERCALLBACK non_crash_dump_request_callback, |
110 WAITORTIMERCALLBACK process_end_callback) | 111 WAITORTIMERCALLBACK process_end_callback) |
111 : crash_dump_request_thread_pool_wait_(INVALID_HANDLE_VALUE), | 112 : crash_dump_request_thread_pool_wait_(INVALID_HANDLE_VALUE), |
112 non_crash_dump_request_thread_pool_wait_(INVALID_HANDLE_VALUE), | 113 non_crash_dump_request_thread_pool_wait_(INVALID_HANDLE_VALUE), |
113 process_end_thread_pool_wait_(INVALID_HANDLE_VALUE), | 114 process_end_thread_pool_wait_(INVALID_HANDLE_VALUE), |
114 lock_(), | 115 lock_(), |
115 port_(port), | 116 port_(port), |
116 delegate_(delegate), | 117 delegate_(delegate), |
117 crash_dump_requested_event_( | 118 crash_dump_requested_event_( |
118 CreateEvent(nullptr, false /* auto reset */, false, nullptr)), | 119 CreateEvent(nullptr, false /* auto reset */, false, nullptr)), |
119 non_crash_dump_requested_event_( | 120 non_crash_dump_requested_event_( |
120 CreateEvent(nullptr, false /* auto reset */, false, nullptr)), | 121 CreateEvent(nullptr, false /* auto reset */, false, nullptr)), |
121 non_crash_dump_completed_event_( | 122 non_crash_dump_completed_event_( |
122 CreateEvent(nullptr, false /* auto reset */, false, nullptr)), | 123 CreateEvent(nullptr, false /* auto reset */, false, nullptr)), |
123 process_(process.Pass()), | 124 process_(process.Pass()), |
124 crash_exception_information_address_( | 125 crash_exception_information_address_( |
125 crash_exception_information_address), | 126 crash_exception_information_address), |
126 non_crash_exception_information_address_( | 127 non_crash_exception_information_address_( |
127 non_crash_exception_information_address) { | 128 non_crash_exception_information_address), |
| 129 debug_critical_section_address_(debug_critical_section_address) { |
128 RegisterThreadPoolWaits(crash_dump_request_callback, | 130 RegisterThreadPoolWaits(crash_dump_request_callback, |
129 non_crash_dump_request_callback, | 131 non_crash_dump_request_callback, |
130 process_end_callback); | 132 process_end_callback); |
131 } | 133 } |
132 | 134 |
133 ~ClientData() { | 135 ~ClientData() { |
134 // It is important that this only access the threadpool waits (it's called | 136 // It is important that this only access the threadpool waits (it's called |
135 // from the main thread) until the waits are unregistered, to ensure that | 137 // from the main thread) until the waits are unregistered, to ensure that |
136 // any outstanding callbacks are complete. | 138 // any outstanding callbacks are complete. |
137 UnregisterThreadPoolWaits(); | 139 UnregisterThreadPoolWaits(); |
(...skipping 10 matching lines...) Expand all Loading... |
148 } | 150 } |
149 HANDLE non_crash_dump_completed_event() const { | 151 HANDLE non_crash_dump_completed_event() const { |
150 return non_crash_dump_completed_event_.get(); | 152 return non_crash_dump_completed_event_.get(); |
151 } | 153 } |
152 WinVMAddress crash_exception_information_address() const { | 154 WinVMAddress crash_exception_information_address() const { |
153 return crash_exception_information_address_; | 155 return crash_exception_information_address_; |
154 } | 156 } |
155 WinVMAddress non_crash_exception_information_address() const { | 157 WinVMAddress non_crash_exception_information_address() const { |
156 return non_crash_exception_information_address_; | 158 return non_crash_exception_information_address_; |
157 } | 159 } |
| 160 WinVMAddress debug_critical_section_address() const { |
| 161 return debug_critical_section_address_; |
| 162 } |
158 HANDLE process() const { return process_.get(); } | 163 HANDLE process() const { return process_.get(); } |
159 | 164 |
160 private: | 165 private: |
161 void RegisterThreadPoolWaits( | 166 void RegisterThreadPoolWaits( |
162 WAITORTIMERCALLBACK crash_dump_request_callback, | 167 WAITORTIMERCALLBACK crash_dump_request_callback, |
163 WAITORTIMERCALLBACK non_crash_dump_request_callback, | 168 WAITORTIMERCALLBACK non_crash_dump_request_callback, |
164 WAITORTIMERCALLBACK process_end_callback) { | 169 WAITORTIMERCALLBACK process_end_callback) { |
165 if (!RegisterWaitForSingleObject(&crash_dump_request_thread_pool_wait_, | 170 if (!RegisterWaitForSingleObject(&crash_dump_request_thread_pool_wait_, |
166 crash_dump_requested_event_.get(), | 171 crash_dump_requested_event_.get(), |
167 crash_dump_request_callback, | 172 crash_dump_request_callback, |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
212 base::Lock lock_; | 217 base::Lock lock_; |
213 // Access to these fields must be guarded by lock_. | 218 // Access to these fields must be guarded by lock_. |
214 HANDLE port_; // weak | 219 HANDLE port_; // weak |
215 ExceptionHandlerServer::Delegate* delegate_; // weak | 220 ExceptionHandlerServer::Delegate* delegate_; // weak |
216 ScopedKernelHANDLE crash_dump_requested_event_; | 221 ScopedKernelHANDLE crash_dump_requested_event_; |
217 ScopedKernelHANDLE non_crash_dump_requested_event_; | 222 ScopedKernelHANDLE non_crash_dump_requested_event_; |
218 ScopedKernelHANDLE non_crash_dump_completed_event_; | 223 ScopedKernelHANDLE non_crash_dump_completed_event_; |
219 ScopedKernelHANDLE process_; | 224 ScopedKernelHANDLE process_; |
220 WinVMAddress crash_exception_information_address_; | 225 WinVMAddress crash_exception_information_address_; |
221 WinVMAddress non_crash_exception_information_address_; | 226 WinVMAddress non_crash_exception_information_address_; |
| 227 WinVMAddress debug_critical_section_address_; |
222 | 228 |
223 DISALLOW_COPY_AND_ASSIGN(ClientData); | 229 DISALLOW_COPY_AND_ASSIGN(ClientData); |
224 }; | 230 }; |
225 | 231 |
226 } // namespace internal | 232 } // namespace internal |
227 | 233 |
228 ExceptionHandlerServer::Delegate::~Delegate() { | 234 ExceptionHandlerServer::Delegate::~Delegate() { |
229 } | 235 } |
230 | 236 |
231 ExceptionHandlerServer::ExceptionHandlerServer() | 237 ExceptionHandlerServer::ExceptionHandlerServer() |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
405 | 411 |
406 internal::ClientData* client; | 412 internal::ClientData* client; |
407 { | 413 { |
408 base::AutoLock lock(*service_context.clients_lock()); | 414 base::AutoLock lock(*service_context.clients_lock()); |
409 client = new internal::ClientData( | 415 client = new internal::ClientData( |
410 service_context.port(), | 416 service_context.port(), |
411 service_context.delegate(), | 417 service_context.delegate(), |
412 ScopedKernelHANDLE(client_process), | 418 ScopedKernelHANDLE(client_process), |
413 message.registration.crash_exception_information, | 419 message.registration.crash_exception_information, |
414 message.registration.non_crash_exception_information, | 420 message.registration.non_crash_exception_information, |
| 421 message.registration.critical_section_address, |
415 &OnCrashDumpEvent, | 422 &OnCrashDumpEvent, |
416 &OnNonCrashDumpEvent, | 423 &OnNonCrashDumpEvent, |
417 &OnProcessEnd); | 424 &OnProcessEnd); |
418 service_context.clients()->insert(client); | 425 service_context.clients()->insert(client); |
419 } | 426 } |
420 | 427 |
421 // Duplicate the events back to the client so they can request a dump. | 428 // Duplicate the events back to the client so they can request a dump. |
422 ServerToClientMessage response; | 429 ServerToClientMessage response; |
423 response.registration.request_crash_dump_event = | 430 response.registration.request_crash_dump_event = |
424 base::checked_cast<uint32_t>(reinterpret_cast<uintptr_t>(DuplicateEvent( | 431 base::checked_cast<uint32_t>(reinterpret_cast<uintptr_t>(DuplicateEvent( |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
458 } | 465 } |
459 | 466 |
460 // static | 467 // static |
461 void __stdcall ExceptionHandlerServer::OnCrashDumpEvent(void* ctx, BOOLEAN) { | 468 void __stdcall ExceptionHandlerServer::OnCrashDumpEvent(void* ctx, BOOLEAN) { |
462 // This function is executed on the thread pool. | 469 // This function is executed on the thread pool. |
463 internal::ClientData* client = reinterpret_cast<internal::ClientData*>(ctx); | 470 internal::ClientData* client = reinterpret_cast<internal::ClientData*>(ctx); |
464 base::AutoLock lock(*client->lock()); | 471 base::AutoLock lock(*client->lock()); |
465 | 472 |
466 // Capture the exception. | 473 // Capture the exception. |
467 unsigned int exit_code = client->delegate()->ExceptionHandlerServerException( | 474 unsigned int exit_code = client->delegate()->ExceptionHandlerServerException( |
468 client->process(), client->crash_exception_information_address()); | 475 client->process(), |
| 476 client->crash_exception_information_address(), |
| 477 client->debug_critical_section_address()); |
469 | 478 |
470 TerminateProcess(client->process(), exit_code); | 479 TerminateProcess(client->process(), exit_code); |
471 } | 480 } |
472 | 481 |
473 // static | 482 // static |
474 void __stdcall ExceptionHandlerServer::OnNonCrashDumpEvent(void* ctx, BOOLEAN) { | 483 void __stdcall ExceptionHandlerServer::OnNonCrashDumpEvent(void* ctx, BOOLEAN) { |
475 // This function is executed on the thread pool. | 484 // This function is executed on the thread pool. |
476 internal::ClientData* client = reinterpret_cast<internal::ClientData*>(ctx); | 485 internal::ClientData* client = reinterpret_cast<internal::ClientData*>(ctx); |
477 base::AutoLock lock(*client->lock()); | 486 base::AutoLock lock(*client->lock()); |
478 | 487 |
479 // Capture the exception. | 488 // Capture the exception. |
480 client->delegate()->ExceptionHandlerServerException( | 489 client->delegate()->ExceptionHandlerServerException( |
481 client->process(), client->non_crash_exception_information_address()); | 490 client->process(), |
| 491 client->non_crash_exception_information_address(), |
| 492 client->debug_critical_section_address()); |
482 | 493 |
483 bool result = SetEvent(client->non_crash_dump_completed_event()); | 494 bool result = SetEvent(client->non_crash_dump_completed_event()); |
484 PLOG_IF(ERROR, !result) << "SetEvent"; | 495 PLOG_IF(ERROR, !result) << "SetEvent"; |
485 } | 496 } |
486 | 497 |
487 // static | 498 // static |
488 void __stdcall ExceptionHandlerServer::OnProcessEnd(void* ctx, BOOLEAN) { | 499 void __stdcall ExceptionHandlerServer::OnProcessEnd(void* ctx, BOOLEAN) { |
489 // This function is executed on the thread pool. | 500 // This function is executed on the thread pool. |
490 internal::ClientData* client = reinterpret_cast<internal::ClientData*>(ctx); | 501 internal::ClientData* client = reinterpret_cast<internal::ClientData*>(ctx); |
491 base::AutoLock lock(*client->lock()); | 502 base::AutoLock lock(*client->lock()); |
492 | 503 |
493 // Post back to the main thread to have it delete this client record. | 504 // Post back to the main thread to have it delete this client record. |
494 PostQueuedCompletionStatus(client->port(), 0, ULONG_PTR(client), nullptr); | 505 PostQueuedCompletionStatus(client->port(), 0, ULONG_PTR(client), nullptr); |
495 } | 506 } |
496 | 507 |
497 } // namespace crashpad | 508 } // namespace crashpad |
OLD | NEW |