| 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 |