OLD | NEW |
1 // Copyright 2014 The Crashpad Authors. All rights reserved. | 1 // Copyright 2014 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 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
157 database, | 157 database, |
158 url, | 158 url, |
159 annotations, | 159 annotations, |
160 arguments, | 160 arguments, |
161 receive_right.Pass(), | 161 receive_right.Pass(), |
162 handler_restarter.get(), | 162 handler_restarter.get(), |
163 false)) { | 163 false)) { |
164 return base::mac::ScopedMachSendRight(); | 164 return base::mac::ScopedMachSendRight(); |
165 } | 165 } |
166 | 166 |
167 if (handler_restarter && handler_restarter->StartRestartThread( | 167 if (handler_restarter && |
| 168 handler_restarter->StartRestartThread( |
168 handler, database, url, annotations, arguments)) { | 169 handler, database, url, annotations, arguments)) { |
169 // The thread owns the object now. | 170 // The thread owns the object now. |
170 ignore_result(handler_restarter.release()); | 171 ignore_result(handler_restarter.release()); |
171 } | 172 } |
172 | 173 |
173 // If StartRestartThread() failed, proceed without the ability to restart. | 174 // If StartRestartThread() failed, proceed without the ability to restart. |
174 // handler_restarter will be released when this function returns. | 175 // handler_restarter will be released when this function returns. |
175 | 176 |
176 return send_right; | 177 return send_right; |
177 } | 178 } |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 //! Failures include failure to start the handler process and failure to | 239 //! Failures include failure to start the handler process and failure to |
239 //! rendezvous with it via ChildPortHandshake. | 240 //! rendezvous with it via ChildPortHandshake. |
240 static bool CommonStart(const base::FilePath& handler, | 241 static bool CommonStart(const base::FilePath& handler, |
241 const base::FilePath& database, | 242 const base::FilePath& database, |
242 const std::string& url, | 243 const std::string& url, |
243 const std::map<std::string, std::string>& annotations, | 244 const std::map<std::string, std::string>& annotations, |
244 const std::vector<std::string>& arguments, | 245 const std::vector<std::string>& arguments, |
245 base::mac::ScopedMachReceiveRight receive_right, | 246 base::mac::ScopedMachReceiveRight receive_right, |
246 HandlerStarter* handler_restarter, | 247 HandlerStarter* handler_restarter, |
247 bool restart) { | 248 bool restart) { |
| 249 DCHECK(!restart || handler_restarter); |
| 250 |
248 if (handler_restarter) { | 251 if (handler_restarter) { |
249 // The port-destroyed notification must be requested each time. It uses | 252 // The port-destroyed notification must be requested each time. It uses |
250 // a send-once right, so once the notification is received, it won’t be | 253 // a send-once right, so once the notification is received, it won’t be |
251 // sent again unless re-requested. | 254 // sent again unless re-requested. |
252 mach_port_t previous; | 255 mach_port_t previous; |
253 kern_return_t kr = | 256 kern_return_t kr = |
254 mach_port_request_notification(mach_task_self(), | 257 mach_port_request_notification(mach_task_self(), |
255 receive_right.get(), | 258 receive_right.get(), |
256 MACH_NOTIFY_PORT_DESTROYED, | 259 MACH_NOTIFY_PORT_DESTROYED, |
257 0, | 260 0, |
258 handler_restarter->notify_port_.get(), | 261 handler_restarter->notify_port_.get(), |
259 MACH_MSG_TYPE_MAKE_SEND_ONCE, | 262 MACH_MSG_TYPE_MAKE_SEND_ONCE, |
260 &previous); | 263 &previous); |
261 if (kr != KERN_SUCCESS) { | 264 if (kr != KERN_SUCCESS) { |
262 MACH_LOG(WARNING, kr) << "mach_port_request_notification"; | 265 MACH_LOG(WARNING, kr) << "mach_port_request_notification"; |
263 | 266 |
264 // This will cause the restart thread to terminate after this restart | 267 // This will cause the restart thread to terminate after this restart |
265 // attempt. There’s no longer any need for it, because no more | 268 // attempt. There’s no longer any need for it, because no more |
266 // port-destroyed notifications can be delivered. | 269 // port-destroyed notifications can be delivered. |
267 handler_restarter->notify_port_.reset(); | 270 handler_restarter->notify_port_.reset(); |
268 } else { | 271 } else { |
269 base::mac::ScopedMachSendRight previous_owner(previous); | 272 base::mac::ScopedMachSendRight previous_owner(previous); |
270 DCHECK(restart || !previous_owner.is_valid()); | 273 DCHECK(restart || !previous_owner.is_valid()); |
271 } | 274 } |
272 | 275 |
273 if (handler_restarter->last_start_time_) { | 276 if (restart) { |
274 // If the handler was ever started before, don’t restart it too quickly. | 277 // If the handler was ever started before, don’t restart it too quickly. |
275 const uint64_t kNanosecondsPerSecond = 1E9; | 278 const uint64_t kNanosecondsPerSecond = 1E9; |
276 const uint64_t kMinimumStartInterval = 1 * kNanosecondsPerSecond; | 279 const uint64_t kMinimumStartInterval = 1 * kNanosecondsPerSecond; |
277 | 280 |
278 const uint64_t earliest_next_start_time = | 281 const uint64_t earliest_next_start_time = |
279 handler_restarter->last_start_time_ + kMinimumStartInterval; | 282 handler_restarter->last_start_time_ + kMinimumStartInterval; |
280 const uint64_t now_time = ClockMonotonicNanoseconds(); | 283 const uint64_t now_time = ClockMonotonicNanoseconds(); |
281 if (earliest_next_start_time > now_time) { | 284 if (earliest_next_start_time > now_time) { |
| 285 const uint64_t sleep_time = earliest_next_start_time - now_time; |
| 286 LOG(INFO) << "restarting handler" |
| 287 << base::StringPrintf(" in %.3fs", |
| 288 static_cast<double>(sleep_time) / |
| 289 kNanosecondsPerSecond); |
282 SleepNanoseconds(earliest_next_start_time - now_time); | 290 SleepNanoseconds(earliest_next_start_time - now_time); |
| 291 } else { |
| 292 LOG(INFO) << "restarting handler"; |
283 } | 293 } |
284 } | 294 } |
285 | 295 |
286 handler_restarter->last_start_time_ = ClockMonotonicNanoseconds(); | 296 handler_restarter->last_start_time_ = ClockMonotonicNanoseconds(); |
287 } | 297 } |
288 | 298 |
289 // Set up the arguments for execve() first. These aren’t needed until | 299 // Set up the arguments for execve() first. These aren’t needed until |
290 // execve() is called, but it’s dangerous to do this in a child process | 300 // execve() is called, but it’s dangerous to do this in a child process |
291 // after fork(). | 301 // after fork(). |
292 ChildPortHandshake child_port_handshake; | 302 ChildPortHandshake child_port_handshake; |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
510 const base::FilePath& database, | 520 const base::FilePath& database, |
511 const std::string& url, | 521 const std::string& url, |
512 const std::map<std::string, std::string>& annotations, | 522 const std::map<std::string, std::string>& annotations, |
513 const std::vector<std::string>& arguments, | 523 const std::vector<std::string>& arguments, |
514 bool restartable) { | 524 bool restartable) { |
515 DCHECK(!exception_port_.is_valid()); | 525 DCHECK(!exception_port_.is_valid()); |
516 | 526 |
517 // The “restartable” behavior can only be selected on OS X 10.10 and later. In | 527 // The “restartable” behavior can only be selected on OS X 10.10 and later. In |
518 // previous OS versions, if the initial client were to crash while attempting | 528 // previous OS versions, if the initial client were to crash while attempting |
519 // to restart the handler, it would become an unkillable process. | 529 // to restart the handler, it would become an unkillable process. |
520 base::mac::ScopedMachSendRight exception_port(HandlerStarter::InitialStart( | 530 base::mac::ScopedMachSendRight exception_port( |
521 handler, | 531 HandlerStarter::InitialStart(handler, |
522 database, | 532 database, |
523 url, | 533 url, |
524 annotations, | 534 annotations, |
525 arguments, | 535 arguments, |
526 restartable && MacOSXMinorVersion() >= 10)); | 536 restartable && MacOSXMinorVersion() >= 10)); |
527 if (!exception_port.is_valid()) { | 537 if (!exception_port.is_valid()) { |
528 return false; | 538 return false; |
529 } | 539 } |
530 | 540 |
531 SetHandlerMachPort(exception_port.Pass()); | 541 SetHandlerMachPort(exception_port.Pass()); |
532 return true; | 542 return true; |
533 } | 543 } |
534 | 544 |
535 bool CrashpadClient::SetHandlerMachService(const std::string& service_name) { | 545 bool CrashpadClient::SetHandlerMachService(const std::string& service_name) { |
536 base::mac::ScopedMachSendRight exception_port(BootstrapLookUp(service_name)); | 546 base::mac::ScopedMachSendRight exception_port(BootstrapLookUp(service_name)); |
(...skipping 23 matching lines...) Expand all Loading... |
560 system_crash_reporter_handler(SystemCrashReporterHandler()); | 570 system_crash_reporter_handler(SystemCrashReporterHandler()); |
561 | 571 |
562 // Proceed even if SystemCrashReporterHandler() failed, setting MACH_PORT_NULL | 572 // Proceed even if SystemCrashReporterHandler() failed, setting MACH_PORT_NULL |
563 // to clear the current exception ports. | 573 // to clear the current exception ports. |
564 if (!SetCrashExceptionPorts(system_crash_reporter_handler.get())) { | 574 if (!SetCrashExceptionPorts(system_crash_reporter_handler.get())) { |
565 SetCrashExceptionPorts(MACH_PORT_NULL); | 575 SetCrashExceptionPorts(MACH_PORT_NULL); |
566 } | 576 } |
567 } | 577 } |
568 | 578 |
569 } // namespace crashpad | 579 } // namespace crashpad |
OLD | NEW |