// 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/sys/appmgr/crash_introspector.h"

#include <fuchsia/sys/internal/cpp/fidl.h>
#include <zircon/assert.h>
#include <zircon/errors.h>
#include <zircon/status.h>
#include <zircon/syscalls/exception.h>
#include <zircon/types.h>

#include <memory>
#include <utility>

#include "lib/async/cpp/task.h"
#include "lib/async/default.h"
#include "lib/fidl/cpp/clone.h"
#include "lib/fit/defer.h"
#include "lib/fitx/result.h"
#include "src/lib/fsl/handles/object_info.h"

namespace component {

using fuchsia::sys::internal::CrashIntrospect_FindComponentByThreadKoid_Response;
using fuchsia::sys::internal::CrashIntrospect_FindComponentByThreadKoid_Result;

// Exceptions have a TTL of 5 minutes in the exception handler so this timeout should be higher
// to preserve the mapping for exceptions that have expired. There is still a chance that exception
// handling takes longer, but we at least want to cover expired exceptions.
const zx::duration kDefaultThreadCacheTimeout = zx::min(10);

CrashIntrospector::CrashIntrospector() : weak_ptr_factory_(this) {}

CrashIntrospector::~CrashIntrospector() = default;

void CrashIntrospector::AddBinding(
    fidl::InterfaceRequest<fuchsia::sys::internal::CrashIntrospect> request) {
  bindings_.AddBinding(this, std::move(request));
}

void CrashIntrospector::FindComponentByThreadKoid(zx_koid_t thread_koid,
                                                  FindComponentByThreadKoidCallback callback) {
  CrashIntrospect_FindComponentByThreadKoid_Result result;
  auto status = RemoveThreadFromCache(thread_koid);
  if (status.is_ok()) {
    CrashIntrospect_FindComponentByThreadKoid_Response response;
    response.component_info = std::move(status.value());
    result.set_response(std::move(response));
  } else {
    result.set_err(ZX_ERR_NOT_FOUND);
  }

  callback(std::move(result));
}

void CrashIntrospector::RegisterExceptionChannel(
    zx::channel exception_channel, fuchsia::sys::internal::SourceIdentity component_info) {
  auto monitor = std::make_unique<CrashMonitor>(
      weak_ptr_factory_.GetWeakPtr(), std::move(exception_channel), std::move(component_info));
  monitors_.emplace(monitor.get(), std::move(monitor));
}

std::unique_ptr<CrashIntrospector::CrashMonitor> CrashIntrospector::ExtractMonitor(
    const CrashIntrospector::CrashMonitor* monitor) {
  auto it = monitors_.find(monitor);
  if (it == monitors_.end()) {
    return nullptr;
  }
  auto obj = std::move(it->second);
  monitors_.erase(it);
  return obj;
}

fitx::result<bool, fuchsia::sys::internal::SourceIdentity> CrashIntrospector::RemoveThreadFromCache(
    zx_koid_t thread_koid) {
  auto it = thread_cache_.find(thread_koid);
  if (it == thread_cache_.end()) {
    return fitx::error(false);
  }
  auto obj = std::move(it->second);
  // already removed, cancel auto removal task if pending
  obj.first->Cancel();
  thread_cache_.erase(it);
  return fitx::ok(std::move(obj.second));
}

void CrashIntrospector::AddThreadToCache(
    const zx::thread& thread, const fuchsia::sys::internal::SourceIdentity& component_info) {
  const auto thread_koid = fsl::GetKoid(thread.get());
  if (thread_cache_.count(thread_koid) > 0) {
    FX_LOGS(ERROR) << "Thread " << thread_koid << " already in map.";
    return;
  }

  auto timeout_task = std::make_unique<async::TaskClosure>([this, thread_koid]() {
    auto result = RemoveThreadFromCache(thread_koid);
    // result will die at end of this statement
  });

  timeout_task->PostDelayed(async_get_default_dispatcher(), kDefaultThreadCacheTimeout);

  thread_cache_.emplace(thread_koid,
                        std::make_pair(std::move(timeout_task), fidl::Clone(component_info)));
}

CrashIntrospector::CrashMonitor::CrashMonitor(fxl::WeakPtr<CrashIntrospector> introspector,
                                              zx::channel exception_channel,
                                              fuchsia::sys::internal::SourceIdentity component_info)
    : introspector_(std::move(introspector)),
      component_info_(std::move(component_info)),
      exception_channel_(std::move(exception_channel)),
      wait_(this, exception_channel_.get(), ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED) {
  wait_.Begin(async_get_default_dispatcher());
}

void CrashIntrospector::CrashMonitor::CrashHandler(async_dispatcher_t* dispatcher,
                                                   async::WaitBase* wait, zx_status_t status,
                                                   const zx_packet_signal* signal) {
  FX_CHECK(status == ZX_OK) << "status: " << status;

  if (signal->observed & ZX_CHANNEL_READABLE) {
    // wait for next signal
    auto run_again = fit::defer([&wait, &dispatcher] { wait->Begin(dispatcher); });
    zx_exception_info_t info;
    zx::exception exception;
    if (const zx_status_t status = exception_channel_.read(
            0, &info, exception.reset_and_get_address(), sizeof(info), 1, nullptr, nullptr);
        status != ZX_OK) {
      FX_LOGS(ERROR) << "Failed to read from the exception channel: " << status;
      return;
    }
    zx::thread thread;
    if (const zx_status_t status = exception.get_thread(&thread); status != ZX_OK) {
      FX_LOGS(ERROR) << "Could not get thread for exception: " << status;

      return;
    }

    if (introspector_) {
      introspector_->AddThreadToCache(thread, component_info_);
    } else {
      run_again.cancel();
      // parent is already dead
      wait_.Cancel();
    }
    return;
  }
  FX_CHECK(signal->observed & ZX_CHANNEL_PEER_CLOSED) << "signal observed: " << signal->observed;
  // job died, stop monitoring
  wait_.Cancel();
  if (introspector_) {
    auto self = introspector_->ExtractMonitor(this);
    // |self| will die when this block finishes
  }
  // this object will die when this function returns
}

CrashIntrospector::CrashMonitor::~CrashMonitor() = default;

}  // namespace component
