// 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 "fbl/auto_call.h"
#include "lib/async/cpp/task.h"
#include "lib/async/default.h"
#include "lib/fidl/cpp/clone.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::RegisterJob(const zx::job& job,
                                    fuchsia::sys::internal::SourceIdentity component_info) {
  zx::channel exception_channel;
  job.create_exception_channel(0, &exception_channel);
  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 = fbl::MakeAutoCall([&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
