// Copyright 2018 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/debug/shared/message_loop_fuchsia.h"

#include <lib/fdio/io.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/zx/clock.h>
#include <lib/zx/handle.h>
#include <lib/zx/job.h>
#include <lib/zx/process.h>
#include <stdio.h>
#include <zircon/syscalls/exception.h>

#include "src/developer/debug/shared/event_handlers.h"
#include "src/developer/debug/shared/logging/logging.h"
#include "src/developer/debug/shared/message_loop.h"
#include "src/developer/debug/shared/socket_watcher.h"
#include "src/developer/debug/shared/zircon_exception_watcher.h"
#include "src/developer/debug/shared/zx_status.h"

namespace debug {

MessageLoopFuchsia::MessageLoopFuchsia() : loop_(&kAsyncLoopConfigAttachToCurrentThread) {}

MessageLoopFuchsia::~MessageLoopFuchsia() {
  FX_DCHECK(Current() != this);  // Cleanup should have been called.
}

bool MessageLoopFuchsia::Init(std::string* error_message) {
  FX_DCHECK(error_message);  // Error message out param not optional.
  if (!MessageLoop::Init(error_message))
    return false;

  zx::event::create(0, &task_event_);

  WatchInfo info;
  info.type = WatchType::kTask;
  zx_status_t status = AddSignalHandler(kTaskSignalKey, task_event_.get(), kTaskSignal, &info);

  if (status != ZX_OK) {
    *error_message = "Could not initialize message loop: ";
    error_message->append(debug::ZxStatusToString(status));
    return false;
  }

  watches_[kTaskSignalKey] = std::move(info);
  return true;
}

void MessageLoopFuchsia::Cleanup() {
  DEBUG_LOG(MessageLoop) << "Cleaning up the message loop.";

  // Destruct the FDWatcher first, because they may call StopWatching and expect some key is still
  // in watches_ and signal_handlers_.
  std::vector<FDWatcher> to_delete;
  to_delete.reserve(watches_.size());
  for (auto& [key, info] : watches_) {
    to_delete.push_back(std::move(info.fd_watcher));
  }
  to_delete.clear();
  watches_.clear();

  // We need to remove the signal/exception handlers/watches before the message loop
  // goes away.
  signal_handlers_.clear();
  channel_exception_handlers_.clear();

  MessageLoop::Cleanup();
}

// static
MessageLoopFuchsia* MessageLoopFuchsia::Current() {
  return reinterpret_cast<MessageLoopFuchsia*>(MessageLoop::Current());
}

const MessageLoopFuchsia::WatchInfo* MessageLoopFuchsia::FindWatchInfo(int id) const {
  auto it = watches_.find(id);
  if (it == watches_.end())
    return nullptr;
  return &it->second;
}

zx_status_t MessageLoopFuchsia::AddSignalHandler(int id, zx_handle_t object, zx_signals_t signals,
                                                 WatchInfo* associated_info) {
  SignalHandler handler;
  zx_status_t status = handler.Init(id, object, signals);
  if (status != ZX_OK)
    return status;

  // The handler should not be there already.
  FX_DCHECK(signal_handlers_.find(handler.handle()) == signal_handlers_.end());

  associated_info->signal_handler_key = handler.handle();
  signal_handlers_[handler.handle()] = std::move(handler);

  return ZX_OK;
}

zx_status_t MessageLoopFuchsia::AddChannelExceptionHandler(int id, zx_handle_t object,
                                                           uint32_t options, WatchInfo* info) {
  ChannelExceptionHandler handler;
  zx_status_t status = handler.Init(id, object, options);
  if (status != ZX_OK)
    return status;

  // The handler should not be there already.
  FX_DCHECK(channel_exception_handlers_.find(handler.handle()) ==
            channel_exception_handlers_.end());

  info->exception_channel_handler_key = handler.handle();
  channel_exception_handlers_[handler.handle()] = std::move(handler);

  return ZX_OK;
}

MessageLoop::WatchHandle MessageLoopFuchsia::WatchFD(WatchMode mode, int fd, FDWatcher watcher) {
  WatchInfo info;
  info.type = WatchType::kFdio;
  info.mode = mode;
  info.fd_watcher = std::move(watcher);
  info.fd = fd;
  info.fdio = fdio_unsafe_fd_to_io(fd);
  if (!info.fdio)
    return WatchHandle();

  uint32_t events = 0;
  switch (mode) {
    case WatchMode::kRead:
      events = POLLIN;
      break;
    case WatchMode::kWrite:
      events = POLLOUT;
      break;
    case WatchMode::kReadWrite:
      events = POLLIN | POLLOUT;
      break;
  }

  zx_signals_t signals = ZX_SIGNAL_NONE;
  fdio_unsafe_wait_begin(info.fdio, events, &info.fd_handle, &signals);
  if (info.fd_handle == ZX_HANDLE_INVALID)
    return WatchHandle();

  int watch_id;
  {
    std::lock_guard<std::mutex> guard(mutex_);

    watch_id = next_watch_id_;
    next_watch_id_++;
  }

  zx_status_t status = AddSignalHandler(watch_id, info.fd_handle, signals, &info);
  if (status != ZX_OK)
    return WatchHandle();

  watches_[watch_id] = std::move(info);
  return WatchHandle(this, watch_id);
}

zx_status_t MessageLoopFuchsia::WatchSocket(WatchMode mode, zx_handle_t socket_handle,
                                            SocketWatcher* watcher, MessageLoop::WatchHandle* out) {
  WatchInfo info;
  info.type = WatchType::kSocket;
  info.mode = mode;
  info.socket_watcher = watcher;
  info.socket_handle = socket_handle;

  int watch_id;
  {
    std::lock_guard<std::mutex> guard(mutex_);

    watch_id = next_watch_id_;
    next_watch_id_++;
  }

  zx_signals_t signals = ZX_SOCKET_PEER_CLOSED;
  if (mode == WatchMode::kRead || mode == WatchMode::kReadWrite)
    signals |= ZX_SOCKET_READABLE;

  if (mode == WatchMode::kWrite || mode == WatchMode::kReadWrite)
    signals |= ZX_SOCKET_WRITABLE;

  zx_status_t status = AddSignalHandler(watch_id, socket_handle, signals, &info);
  if (status != ZX_OK)
    return status;

  watches_[watch_id] = std::move(info);
  *out = WatchHandle(this, watch_id);
  return ZX_OK;
}

zx_status_t MessageLoopFuchsia::WatchProcessExceptions(WatchProcessConfig config,
                                                       MessageLoop::WatchHandle* out) {
  WatchInfo info;
  info.resource_name = config.process_name;
  info.type = WatchType::kProcessExceptions;
  info.exception_watcher = config.watcher;
  info.task_koid = config.process_koid;
  info.task_handle = config.process_handle;

  int watch_id;
  {
    std::lock_guard<std::mutex> guard(mutex_);

    watch_id = next_watch_id_;
    next_watch_id_++;
  }

  // Watch all exceptions for the process.
  zx_status_t status;
  status = AddChannelExceptionHandler(watch_id, config.process_handle,
                                      ZX_EXCEPTION_CHANNEL_DEBUGGER, &info);
  if (status != ZX_OK)
    return status;

  // Watch for the process terminated signal.
  status = AddSignalHandler(watch_id, config.process_handle, ZX_PROCESS_TERMINATED, &info);
  if (status != ZX_OK)
    return status;

  DEBUG_LOG(MessageLoop) << "Watching process " << info.resource_name;

  watches_[watch_id] = std::move(info);
  *out = WatchHandle(this, watch_id);
  return ZX_OK;
}

zx_status_t MessageLoopFuchsia::WatchJobExceptions(WatchJobConfig config,
                                                   MessageLoop::WatchHandle* out) {
  WatchInfo info;
  info.resource_name = config.job_name;
  info.type = WatchType::kJobExceptions;
  info.exception_watcher = config.watcher;
  info.task_koid = config.job_koid;
  info.task_handle = config.job_handle;

  int watch_id;
  {
    std::lock_guard<std::mutex> guard(mutex_);

    watch_id = next_watch_id_;
    next_watch_id_++;
  }

  // Create and track the exception handle.
  zx_status_t status =
      AddChannelExceptionHandler(watch_id, config.job_handle, ZX_EXCEPTION_CHANNEL_DEBUGGER, &info);
  if (status != ZX_OK)
    return status;

  DEBUG_LOG(MessageLoop) << "Watching job " << info.resource_name;

  watches_[watch_id] = std::move(info);
  *out = WatchHandle(this, watch_id);
  return ZX_OK;
}

bool MessageLoopFuchsia::CheckAndProcessPendingTasks() {
  std::lock_guard<std::mutex> guard(mutex_);

  // We clear the event, otherwise it will trigger again and again
  task_event_.signal(kTaskSignal, 0);

  // Do a C++ task.
  if (ProcessPendingTask()) {
    SetHasTasks();  // Enqueue another task signal.
    return true;
  }
  return false;
}

void MessageLoopFuchsia::HandleChannelException(const ChannelExceptionHandler& handler,
                                                zx::exception exception,
                                                zx_exception_info_t exception_info) {
  WatchInfo* watch_info = nullptr;
  {
    std::lock_guard<std::mutex> lock(mutex_);
    auto it = watches_.find(handler.watch_info_id());
    FX_DCHECK(it != watches_.end());
    watch_info = &it->second;
  }

  if (watch_info->type != WatchType::kProcessExceptions &&
      watch_info->type != WatchType::kJobExceptions) {
    FX_NOTREACHED() << "Should only receive exceptions.";
    return;
  }

  FX_DCHECK(watch_info->exception_watcher);

  // We should only receive exceptions here.
  switch (watch_info->type) {
    case WatchType::kTask:
    case WatchType::kFdio:
    case WatchType::kSocket:
      FX_NOTREACHED() << "Should only receive exceptions.";
      return;
    case WatchType::kProcessExceptions:
      OnProcessException(*watch_info, std::move(exception), exception_info);
      return;
    case WatchType::kJobExceptions:
      OnJobException(*watch_info, std::move(exception), exception_info);
      return;
  }

  FX_NOTREACHED();
}

uint64_t MessageLoopFuchsia::GetMonotonicNowNS() const {
  zx::time ret = zx::clock::get_monotonic();

  return ret.get();
}

// Previously, the approach was to first look for C++ tasks and when handled look for WatchHandle
// work and finally wait for an event. This worked because handle events didn't post C++ tasks.
//
// But some tests do post tasks on handle events. Because C++ tasks are signaled by explicitly
// signaling an zx::event, without manually checking, the C++ tasks will never be checked and we
// would get blocked until a watch handled is triggered.
//
// In order to handle the events properly, we need to check for C++ tasks before and *after*
// handling watch handle events. This way we always process C++ tasks before handle events and will
// get signaled if one of them posted a new task.
void MessageLoopFuchsia::RunImpl() {
  // Init should have been called.
  FX_DCHECK(Current() == this);
  zx_status_t status;

  zx::time time;
  uint64_t delay = DelayNS();
  if (delay == MessageLoop::kMaxDelay) {
    time = zx::time::infinite();
  } else {
    time = zx::deadline_after(zx::nsec(delay));
  }

  while (!should_quit()) {
    status = loop_.ResetQuit();
    FX_DCHECK(status != ZX_ERR_BAD_STATE);
    status = loop_.Run(time);
    FX_DCHECK(status == ZX_OK || status == ZX_ERR_CANCELED || status == ZX_ERR_TIMED_OUT)
        << "Expected ZX_OK || ZX_ERR_CANCELED || ZX_ERR_TIMED_OUT, got "
        << ZxStatusToString(status);

    if (status != ZX_ERR_TIMED_OUT) {
      return;
    }

    std::lock_guard<std::mutex> guard(mutex_);
    if (ProcessPendingTask())
      SetHasTasks();
  }
}

void MessageLoopFuchsia::QuitNow() {
  MessageLoop::QuitNow();
  loop_.Quit();
}

void MessageLoopFuchsia::StopWatching(int id) {
  // The dispatch code for watch callbacks requires this be called on the same thread as the message
  // loop is.
  FX_DCHECK(Current() == this);

  std::lock_guard<std::mutex> guard(mutex_);

  auto found = watches_.find(id);
  FX_DCHECK(found != watches_.end());

  WatchInfo& info = found->second;
  // BufferedFD constantly creates and destroys FD handles, flooding the log with non-helpful
  // logging statements.
  if (info.type != WatchType::kFdio) {
    DEBUG_LOG(MessageLoop) << "Stop watching " << WatchTypeToString(info.type) << " "
                           << info.resource_name;
  }

  switch (info.type) {
    case WatchType::kProcessExceptions: {
      RemoveChannelExceptionHandler(&info);
      RemoveSignalHandler(&info);
      break;
    }
    case WatchType::kJobExceptions: {
      RemoveChannelExceptionHandler(&info);
      break;
    }
    case WatchType::kFdio:
      fdio_unsafe_release(info.fdio);
      __FALLTHROUGH;
    case WatchType::kTask:
    case WatchType::kSocket:
      RemoveSignalHandler(&info);
      break;
  }
  watches_.erase(found);
}

void MessageLoopFuchsia::SetHasTasks() { task_event_.signal(0, kTaskSignal); }

void MessageLoopFuchsia::OnFdioSignal(int watch_id, const WatchInfo& info, zx_signals_t observed) {
  uint32_t events = 0;
  fdio_unsafe_wait_end(info.fdio, observed, &events);

  if ((events & POLLERR) || (events & POLLHUP) || (events & POLLNVAL) || (events & POLLRDHUP)) {
    info.fd_watcher(info.fd, false, false, true);

    // Don't dispatch any other notifications when there's an error. Zircon seems to set readable
    // and writable on error even if there's nothing there.
    return;
  }

  // observed is a bitmap of ALL of the signals asserted on the file descripter, which could be a
  // superset of what we expected. Check the watch mode so we don't notify unwanted events.
  bool readable = !!(events & POLLIN) && (info.mode != WatchMode::kWrite);
  bool writable = !!(events & POLLOUT) && (info.mode != WatchMode::kRead);
  info.fd_watcher(info.fd, readable, writable, false);
  // info might be invalid because fd_watcher could have called StopWatching().
}

void MessageLoopFuchsia::RemoveSignalHandler(WatchInfo* info) {
  const async_wait_t* key = info->signal_handler_key;
  FX_DCHECK(key);

  size_t erase_count = signal_handlers_.erase(key);
  FX_DCHECK(erase_count == 1u);

  info->signal_handler_key = nullptr;
}

void MessageLoopFuchsia::RemoveChannelExceptionHandler(WatchInfo* info) {
  const async_wait_t* key = info->exception_channel_handler_key;
  FX_DCHECK(key);

  size_t erase_count = channel_exception_handlers_.erase(key);
  FX_DCHECK(erase_count == 1u);

  info->exception_channel_handler_key = nullptr;
}

void MessageLoopFuchsia::OnProcessException(const WatchInfo& info, zx::exception exception,
                                            zx_exception_info_t exception_info) {
  switch (exception_info.type) {
    case ZX_EXCP_THREAD_STARTING:
      info.exception_watcher->OnThreadStarting(std::move(exception), exception_info);
      break;
    case ZX_EXCP_THREAD_EXITING:
      info.exception_watcher->OnThreadExiting(std::move(exception), exception_info);
      break;
    case ZX_EXCP_GENERAL:
    case ZX_EXCP_FATAL_PAGE_FAULT:
    case ZX_EXCP_UNDEFINED_INSTRUCTION:
    case ZX_EXCP_SW_BREAKPOINT:
    case ZX_EXCP_HW_BREAKPOINT:
    case ZX_EXCP_UNALIGNED_ACCESS:
    case ZX_EXCP_POLICY_ERROR:
      info.exception_watcher->OnException(std::move(exception), exception_info);
      break;
    default:
      FX_NOTREACHED();
  }
}

void MessageLoopFuchsia::OnProcessTerminated(const WatchInfo& info, zx_signals_t observed) {
  FX_DCHECK(observed & ZX_PROCESS_TERMINATED);
  info.exception_watcher->OnProcessTerminated(info.task_koid);
}

void MessageLoopFuchsia::OnJobException(const WatchInfo& info, zx::exception exception,
                                        zx_exception_info_t exception_info) {
  // Currently job exceptions only track process starting exceptions.
  // TODO(fxbug.dev/34167): Debugger job exception ports should receive all exceptions.
  if (exception_info.type != ZX_EXCP_PROCESS_STARTING) {
    FX_NOTREACHED();
    return;
  }

  info.exception_watcher->OnProcessStarting(std::move(exception), exception_info);
}

void MessageLoopFuchsia::OnSocketSignal(int watch_id, const WatchInfo& info,
                                        zx_signals_t observed) {
  if (observed & ZX_SOCKET_PEER_CLOSED) {
    info.socket_watcher->OnSocketError(info.socket_handle);
    return;
  }

  // observed is a bitmap of ALL of the signals asserted on the socket, which could be a superset of
  // what we expected. Check the watch mode so we don't notify unwanted events.
  bool readable = !!(observed & ZX_SOCKET_READABLE) && (info.mode != WatchMode::kWrite);
  bool writable = !!(observed & ZX_SOCKET_WRITABLE) && (info.mode != WatchMode::kRead);

  // Dispatch readable signal.
  if (readable)
    info.socket_watcher->OnSocketReadable(info.socket_handle);

  // When signaling both readable and writable, make sure the readable handler didn't remove the
  // watch.
  if (readable && writable) {
    std::lock_guard<std::mutex> guard(mutex_);
    if (watches_.find(watch_id) == watches_.end())
      return;
  }

  // Dispatch writable signal.
  if (writable)
    info.socket_watcher->OnSocketWritable(info.socket_handle);
}

const char* WatchTypeToString(WatchType type) {
  switch (type) {
    case WatchType::kFdio:
      return "FDIO";
    case WatchType::kJobExceptions:
      return "Job";
    case WatchType::kProcessExceptions:
      return "Process";
    case WatchType::kTask:
      return "Task";
    case WatchType::kSocket:
      return "Socket";
  }

  FX_NOTREACHED();
  return "";
}

}  // namespace debug
