| // Copyright 2020 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. |
| |
| #include "src/developer/forensics/exceptions/handler_manager.h" |
| |
| namespace forensics { |
| namespace exceptions { |
| |
| HandlerManager::HandlerManager(async_dispatcher_t* dispatcher, CrashCounter crash_counter, |
| size_t max_num_handlers, zx::duration exception_ttl) |
| : dispatcher_(dispatcher), |
| crash_counter_(std::move(crash_counter)), |
| exception_ttl_(exception_ttl) { |
| handlers_.reserve(max_num_handlers); |
| for (size_t i = 0; i < max_num_handlers; ++i) { |
| handlers_.emplace_back( |
| dispatcher_, /*log_moniker=*/ |
| [crash_counter = &crash_counter_](const std::string& moniker) { |
| crash_counter->Increment(std::move(moniker)); |
| }, |
| /*on_available=*/ |
| [i, this] { |
| // Push to the front so already initialized handlers are used first. |
| available_handlers_.push_front(i); |
| HandleNextPendingException(); |
| }); |
| available_handlers_.emplace_back(i); |
| } |
| } |
| |
| void HandlerManager::Handle(zx::exception exception) { |
| pending_exceptions_.emplace_back(dispatcher_, exception_ttl_, std::move(exception)); |
| HandleNextPendingException(); |
| } |
| |
| void HandlerManager::HandleNextPendingException() { |
| if (pending_exceptions_.empty() || available_handlers_.empty()) { |
| return; |
| } |
| |
| // We must reserve all state needed to handle the exception (the handler and the exception) and |
| // remove it from the queues prior to actually handling the exception. This is done to prevent |
| // that state from being erroneously being reused when ProcessHandler::Handle ends up calling |
| // HandleNextPendingException on a failure. |
| const size_t handler_idx = available_handlers_.front(); |
| available_handlers_.pop_front(); |
| |
| zx::exception exception = pending_exceptions_.front().TakeException(); |
| zx::process process = pending_exceptions_.front().TakeProcess(); |
| zx::thread thread = pending_exceptions_.front().TakeThread(); |
| |
| pending_exceptions_.pop_front(); |
| |
| handlers_[handler_idx].Handle(std::move(exception), std::move(process), std::move(thread)); |
| } |
| |
| } // namespace exceptions |
| } // namespace forensics |