// 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/zxdb/client/thread_impl.h"

#include <inttypes.h>
#include <lib/syslog/cpp/macros.h>

#include <iostream>
#include <limits>

#include "src/developer/debug/ipc/protocol.h"
#include "src/developer/debug/ipc/records.h"
#include "src/developer/debug/ipc/unwinder_support.h"
#include "src/developer/debug/shared/logging/logging.h"
#include "src/developer/debug/shared/message_loop.h"
#include "src/developer/debug/shared/register_info.h"
#include "src/developer/debug/shared/zx_status.h"
#include "src/developer/debug/zxdb/client/breakpoint.h"
#include "src/developer/debug/zxdb/client/breakpoint_observer.h"
#include "src/developer/debug/zxdb/client/elf_memory_region.h"
#include "src/developer/debug/zxdb/client/frame_impl.h"
#include "src/developer/debug/zxdb/client/process_impl.h"
#include "src/developer/debug/zxdb/client/remote_api.h"
#include "src/developer/debug/zxdb/client/session.h"
#include "src/developer/debug/zxdb/client/setting_schema_definition.h"
#include "src/developer/debug/zxdb/client/target_impl.h"
#include "src/developer/debug/zxdb/client/thread_controller.h"
#include "src/developer/debug/zxdb/common/join_callbacks.h"
#include "src/developer/debug/zxdb/expr/cast.h"
#include "src/developer/debug/zxdb/expr/expr.h"
#include "src/developer/debug/zxdb/symbols/loaded_module_symbols.h"
#include "src/developer/debug/zxdb/symbols/process_symbols.h"
#include "src/lib/unwinder/unwind.h"

namespace zxdb {

namespace {

// Maximum number of times we'll allow thread controller to return "kFuture" before we declare
// they're in an infinite loop. Normally there will only be one "future" return before calling
// ResumeFromAsyncThreadController() so if we get many it probably indicates a thread controller is
// continuing to return the "future" from the same state and it's stuck (this is an easy mistake).
constexpr int kMaxNestedFutureCompletion = 16;

}  // namespace

ThreadImpl::ThreadImpl(ProcessImpl* process, const debug_ipc::ThreadRecord& record)
    : Thread(process->session()),
      process_(process),
      koid_(record.id.thread),
      stack_(this),
      weak_factory_(this) {
  SetMetadata(record);
  settings_.set_fallback(&process_->target()->settings());

  // Should be at the bottom of this function. This will enable notifications now that
  // initialization is complete.
  allow_notifications_ = true;
}

ThreadImpl::~ThreadImpl() = default;

Process* ThreadImpl::GetProcess() const { return process_; }

uint64_t ThreadImpl::GetKoid() const { return koid_; }

const std::string& ThreadImpl::GetName() const { return name_; }

std::optional<debug_ipc::ThreadRecord::State> ThreadImpl::GetState() const { return state_; }
debug_ipc::ThreadRecord::BlockedReason ThreadImpl::GetBlockedReason() const {
  return blocked_reason_;
}
std::optional<StopInfo> ThreadImpl::CurrentStopInfo() const { return current_stop_info_; }

void ThreadImpl::Pause(fit::callback<void()> on_paused) {
  // The frames may have been requested when the thread was running which will have marked them
  // "empty but complete." When a pause happens the frames will become available so we want
  // subsequent requests to request them.
  ClearState();

  debug_ipc::PauseRequest request;
  request.ids.push_back({.process = process_->GetKoid(), .thread = koid_});

  session()->remote_api()->Pause(
      request, [weak_thread = weak_factory_.GetWeakPtr(), on_paused = std::move(on_paused)](
                   const Err& err, debug_ipc::PauseReply reply) mutable {
        if (!err.has_error() && weak_thread) {
          // Save the new metadata.
          if (reply.threads.size() == 1 && reply.threads[0].id.thread == weak_thread->koid_) {
            weak_thread->SetMetadata(reply.threads[0]);
          } else {
            // If the client thread still exists, the agent's record of that thread should have
            // existed at the time the message was sent so there should be no reason the update
            // doesn't match.
            FX_NOTREACHED();
          }
        }
        on_paused();
      });
}

void ThreadImpl::Continue(bool forward_exception) {
  debug_ipc::ResumeRequest request;
  request.ids.push_back({.process = process_->GetKoid(), .thread = koid_});

  if (controllers_.empty()) {
    if (!forward_exception && current_stop_info_) {
      if (current_stop_info_->exception_type != debug_ipc::ExceptionType::kNone &&
          !debug_ipc::IsDebug(current_stop_info_->exception_type)) {
        // Debug exceptions are excluded since we never want to forward those.
        forward_exception = true;
      }
    }

    request.how = forward_exception ? debug_ipc::ResumeRequest::How::kForwardAndContinue
                                    : debug_ipc::ResumeRequest::How::kResolveAndContinue;
  } else {
    // When there are thread controllers, ask the most recent one for how to continue.
    //
    // Theoretically we're running with all controllers at once and we want to stop at the first one
    // that triggers, which means we want to compute the most restrictive intersection of all of
    // them.
    //
    // This is annoying to implement and it's difficult to construct a situation where this would be
    // required. The controller that doesn't involve breakpoints is "step in range" and generally
    // ranges refer to code lines that will align. Things like "until" are implemented with
    // breakpoints so can overlap arbitrarily with other operations with no problem.
    //
    // A case where this might show up:
    //  1. Do "step into" which steps through a range of instructions.
    //  2. In the middle of that range is a breakpoint that's hit.
    //  3. The user does "finish." We'll ask the finish controller what to do and it will say
    //     "continue" and the range from step 1 is lost.
    // However, in this case probably does want to end up one stack frame back rather than several
    // instructions after the breakpoint due to the original "step into" command, so even when
    // "wrong" this current behavior isn't necessarily bad.
    controllers_.back()->Log("Continuing with this controller as primary.");
    ThreadController::ContinueOp op = controllers_.back()->GetContinueOp();
    if (op.synthetic_stop_) {
      // Synthetic stop. Skip notifying the backend and broadcast a stop notification for the
      // current state.
      controllers_.back()->Log("Synthetic stop.");
      debug::MessageLoop::Current()->PostTask(FROM_HERE, [thread = weak_factory_.GetWeakPtr()]() {
        if (thread) {
          StopInfo info;
          info.exception_type = debug_ipc::ExceptionType::kSynthetic;
          thread->OnException(info);
        }
      });
      return;
    } else {
      // Dispatch the continuation message.
      request.how = op.how;
      request.range_begin = op.range.begin();
      request.range_end = op.range.end();
    }
  }

  ClearState();
  session()->remote_api()->Resume(request, [](const Err& err, debug_ipc::ResumeReply) {});
}

void ThreadImpl::ContinueWith(std::unique_ptr<ThreadController> controller,
                              fit::callback<void(const Err&)> on_continue) {
  ThreadController* controller_ptr = controller.get();

  // Add it first so that its presence will be noted by anything its initialization function does.
  controllers_.push_back(std::move(controller));

  controller_ptr->InitWithThread(
      this, [this, controller_ptr, on_continue = std::move(on_continue)](const Err& err) mutable {
        if (err.has_error()) {
          controller_ptr->Log("InitWithThread failed: %s", err.msg().c_str());
          NotifyControllerDone(controller_ptr);  // Remove the controller.
        } else {
          controller_ptr->Log("Initialized, continuing...");
          Continue(false);
        }
        on_continue(err);
      });
}

void ThreadImpl::AddPostStopTask(PostStopTask task) {
  // This function must only be called from a ThreadController::OnThreadStop() handler.
  FX_DCHECK(handling_on_stop_);
  post_stop_tasks_.push_back(std::move(task));
}

void ThreadImpl::CancelAllThreadControllers() {
  controllers_.clear();
  if (nested_stop_future_completion_) {
    // We're waiting on an async thread controller to complete but just cleared them all. Reissue
    // the exception to clean up the async state and issue stop notifications.
    OnException(async_stop_info_);
  }
}

void ThreadImpl::ResumeFromAsyncThreadController(std::optional<debug_ipc::ExceptionType> type) {
  bool debug_stepping = settings().GetBool(ClientSettings::Thread::kDebugStepping);
  if (debug_stepping)
    printf("↓↓↓↓↓↓↓↓↓↓ Resuming from async thread controller.\r\n");

  if (nested_stop_future_completion_ == 0) {
    // Not waiting on an async thread controller to finish. This could be a programming error but it
    // could also be that somebody called CancelAllThreadControllers() out from under us.
    if (debug_stepping)
      printf("No async stepping in progress, giving up.\r\n");
    return;
  }

  if (type)
    async_stop_info_.exception_type = *type;

  OnException(async_stop_info_);
}

void ThreadImpl::JumpTo(uint64_t new_address, fit::callback<void(const Err&)> cb) {
  // The register to set.
  debug_ipc::WriteRegistersRequest request;
  request.id = {.process = process_->GetKoid(), .thread = koid_};
  request.registers.emplace_back(
      GetSpecialRegisterID(session()->arch(), debug::SpecialRegisterType::kIP), new_address);

  // The "jump" command updates the thread's location so we need to recompute the stack. So once the
  // jump is complete we re-request the thread's status.
  //
  // This could be made faster by requesting status immediately after sending the update so we don't
  // have to wait for two round-trips, but that complicates the callback logic and this feature is
  // not performance- sensitive.
  //
  // Another approach is to make the register request message able to optionally request a stack
  // backtrace and include that in the reply.
  session()->remote_api()->WriteRegisters(
      request, [thread = weak_factory_.GetWeakPtr(), cb = std::move(cb)](
                   const Err& err, debug_ipc::WriteRegistersReply reply) mutable {
        if (err.has_error()) {
          cb(err);  // Transport error.
        } else if (reply.status.has_error()) {
          cb(Err("Could not set thread instruction pointer: " + reply.status.message()));
        } else if (!thread) {
          cb(Err("Thread destroyed."));
        } else {
          // Success, update the current stack before issuing the callback.
          thread->SyncFramesForStack({}, std::move(cb));
        }
      });
}

void ThreadImpl::NotifyControllerDone(ThreadController* controller) {
  controller->Log("Controller done, removing.");

  // We expect to have few controllers so brute-force is sufficient.
  for (auto cur = controllers_.begin(); cur != controllers_.end(); ++cur) {
    if (cur->get() == controller) {
      controllers_.erase(cur);
      return;
    }
  }
  FX_NOTREACHED();  // Notification for unknown controller.
}

void ThreadImpl::StepInstructions(uint64_t count) {
  debug_ipc::ResumeRequest request;
  request.ids.push_back({.process = process_->GetKoid(), .thread = koid_});
  request.how = debug_ipc::ResumeRequest::How::kStepInstruction;
  request.count = count;
  session()->remote_api()->Resume(request, [](const Err& err, debug_ipc::ResumeReply) {});
}

const Stack& ThreadImpl::GetStack() const { return stack_; }

Stack& ThreadImpl::GetStack() { return stack_; }

void ThreadImpl::SetMetadata(const debug_ipc::ThreadRecord& record, bool skip_frames) {
  FX_DCHECK(koid_ == record.id.thread);

  name_ = record.name;
  state_ = record.state;
  blocked_reason_ = record.blocked_reason;

  if (!skip_frames) {
    stack_.SetFrames(record.stack_amount, record.frames);
  }
}

void ThreadImpl::OnException(const StopInfo& info) {
  if (settings().GetBool(ClientSettings::Thread::kDebugStepping)) {
    printf("----------\r\nGot %s exception @ 0x%" PRIx64 " in %s\r\n",
           debug_ipc::ExceptionTypeToString(info.exception_type), stack_[0]->GetAddress(),
           ThreadController::FrameFunctionNameForLog(stack_[0]).c_str());
  }

  if (stack_.empty()) {
    // Threads can stop with no stack if the thread is killed while processing an exception. If
    // this happens (or any other error that might cause an empty stack), declare all thread
    // controllers done since they can't meaningfully continue or process this state, and forcing
    // them all to separately check for an empty stack is error-prone.
    controllers_.clear();
  }

  // Debug tracking for proper usage from OnThreadStop handlers.
  handling_on_stop_ = true;

  // When any controller says "stop" it takes precedence and the thread will stop no matter what
  // any other controllers say.
  bool should_stop = false;

  // Set when any controller says "continue". If no controller says "stop" we need to differentiate
  // the case where there are no controllers or all controllers say "unexpected" (thread should
  // stop), from where one or more said "continue" (thread should continue, any "unexpected" votes
  // are ignored).
  bool have_continue = false;

  auto controller_iter = controllers_.begin();
  while (controller_iter != controllers_.end()) {
    ThreadController* controller = controller_iter->get();
    switch (controller->OnThreadStop(info.exception_type, info.hit_breakpoints)) {
      case ThreadController::kContinue:
        // Try the next controller.
        controller->Log("Reported continue on exception.");
        have_continue = true;
        controller_iter++;
        break;
      case ThreadController::kStopDone:
        // Once a controller tells us to stop, we assume the controller no longer applies and delete
        // it.
        //
        // Need to continue with checking all controllers even though we know we should stop at this
        // point. Multiple controllers should say "stop" at the same time and we need to be able to
        // delete all that no longer apply (say you did "finish", hit a breakpoint, and then
        // "finish" again, both finish commands would be active and you would want them both to be
        // completed when the current frame actually finishes).
        controller->Log("Reported stop on exception, stopping and removing it.");
        controller_iter = controllers_.erase(controller_iter);
        should_stop = true;
        break;
      case ThreadController::kUnexpected:
        // An unexpected exception means the controller is still active but doesn't know what to do
        // with this exception.
        controller->Log("Reported unexpected exception.");
        controller_iter++;
        break;
      case ThreadController::kFuture:
        controller->Log("Returned kFuture, waiting for async completion.");

        nested_stop_future_completion_++;
        if (nested_stop_future_completion_ >= kMaxNestedFutureCompletion) {
          // The thread controllers issued too many sequential "future" stop completions. It's easy
          // to accidentally get into an infinite loop by continuing to return kFuture from the same
          // stop type. This code detects that case and gives up.
          controller->Log(
              "Hit limit for nested 'future' thread controllers. Clearing state and stopping.");
          controllers_.clear();
          should_stop = true;
        } else {
          // Normal good case. Don't do anything and wait for the controller to call
          // ResumeFromAsyncThreadController() to continue.
          //
          // In this case we keep handling_on_stop_ true because we can continue to accumulate
          // post-stop tasks.
          async_stop_info_ = info;
          return;
        }
    }
  }

  handling_on_stop_ = false;
  nested_stop_future_completion_ = 0;

  if (!have_continue && !controllers_.empty()) {
    // No controller voted to continue (maybe all active controllers reported "unexpected"). Such
    // cases should stop.
    should_stop = true;
  }

  // This joiner is responsible for collecting all of the conditional breakpoint evaluation results
  // at this location. Only a single conditional breakpoint needs to evaluate to true to trigger a
  // stop. Unconditional breakpoints will always stop, and if there are only unconditional
  // breakpoints at this location, then this evaluation will happen synchronously.
  auto conditional_breakpoints_callback = fxl::MakeRefCounted<JoinCallbacks<bool>>();

  StopInfo external_info = info;

  // The existence of any non-internal, unconditional breakpoints being hit means the thread should
  // always stop. Breakpoints that have conditional expressions will be evaluated and stop only if
  // the condition is true. This check happens after notifying the controllers so if a controller
  // triggers, it's counted as a "hit" (otherwise, doing "run until" to a line with a normal
  // breakpoint on it would keep the "run until" operation active even after it was hit).
  //
  // Also, filter out internal breakpoints in the notification sent to the observers.
  for (auto it = external_info.hit_breakpoints.begin(); it != external_info.hit_breakpoints.end();
       /* nothing */) {
    if (*it && !it->get()->IsInternal()) {
      auto bp = it->get();

      if (const auto& cond = bp->GetSettings().condition; !cond.empty()) {
        ResolveConditionalBreakpoint(cond, bp, conditional_breakpoints_callback->AddCallback());
      } else {
        // Non-internal, unconditional breakpoints should always stop. Conditional breakpoints will
        // evaluate their expressions (there could be multiple, but only one has to vote to stop)
        // and then decide to stop or not.
        should_stop = true;
      }
      ++it;
    } else {
      // Remove deleted weak pointers and internal breakpoints.
      it = external_info.hit_breakpoints.erase(it);
    }
  }

  // If there are any conditional breakpoints that need to evaluate an expression, the callback(s)
  // will be issued asynchronously and collected into a vector. In the case no asynchronous
  // evaluations need to occur, this will return immediately and issue the callback above.
  conditional_breakpoints_callback->Ready([weak_this = weak_factory_.GetWeakPtr(), should_stop,
                                           external_info](std::vector<bool> results) mutable {
    if (weak_this) {
      bool should_forward = false;

      // This is the case where there's some external exception from the remote thread. We want to
      // ask our owning process what to do too in this case, which may call |Continue| with a
      // different forwarding argument.
      switch (weak_this->process()->OnException(external_info)) {
        case debug_ipc::ResumeRequest::How::kForwardAndContinue: {
          should_forward = true;
          should_stop = false;
          break;
        }
        case debug_ipc::ResumeRequest::How::kResolveAndContinue: {
          should_forward = false;
          should_stop = false;
          break;
        }
        case debug_ipc::ResumeRequest::How::kLast: {
          // The process has no opinion about how to continue, the following checks will determine
          // if we actually stop or not.
          //
          // Non-debug exceptions (most likely a crash is happening) also mean the thread should
          // always stop (check this after running the controllers for the same reason as the
          // breakpoint check above).
          if (external_info.exception_type != debug_ipc::ExceptionType::kNone &&
              !debug_ipc::IsDebug(external_info.exception_type)) {
            should_stop = true;
          }

          if (std::any_of(results.cbegin(), results.cend(), [](bool result) { return result; }))
            should_stop = true;

          // If there are no conditional breakpoints installed here, and there are no running
          // controllers, then we should stop. This case catches things like __builtin_debugtrap()
          // or "int 3" on x86_64 architectures.
          if (!should_stop && results.empty() && weak_this->controllers_.empty()) {
            should_stop = true;
          }
          break;
        }
        default: {
          FX_NOTREACHED();
          break;
        }
      }

      // Execute the chain of post-stop tasks (may be asynchronous) and then dispatch the stop
      // notification or continue operation.
      weak_this->RunNextPostStopTaskOrNotify(external_info, should_stop, should_forward);
    }
  });
}

void ThreadImpl::ResolveConditionalBreakpoint(const std::string& cond, Breakpoint* bp,
                                              fit::callback<void(bool)> cb) {
  // Update the evaluation context to the current stack frame and schedule the expression
  // evaluation.
  auto ctx = GetStack()[0]->GetEvalContext();
  EvalExpression(cond, ctx, true, [this, ctx, bp, cb = std::move(cb)](ErrOrValue val) mutable {
    std::string_view msg;

    if (val.ok()) {
      if (auto cast_result = CastNumericExprValueToBool(ctx, val.value()); cast_result.ok()) {
        // This is the normal good case. The expression resolved to a value that successfully
        // casted to a boolean. We're done.
        cb(cast_result.value());
        return;
      } else {
        // The expression evaluated successfully, but couldn't be cast to a bool.
        msg = cast_result.err().msg();
      }
    } else {
      // The expression couldn't be evaluated.
      msg = val.err().msg();
    }

    // If we get here, the conditional expression failed to evaluate somehow. Show a warning
    // message if the expression resolution fails for some reason. Note: we still want to stop
    // execution here so the user can fix whatever went wrong.
    Err err(
        "Hit conditional breakpoint, but expression evaluation failed:\n%s\nThis location "
        "could have been optimized out, or this variable might not exist in the current scope."
        "\nCheck the expression with `bp <id> get condition`, or modify the expression with "
        "`bp <id> set condition <expr>`.",
        msg.data());

    for (auto& observer : session()->breakpoint_observers()) {
      observer.OnBreakpointUpdateFailure(bp, err);
    }

    cb(true);
  });
}

void ThreadImpl::SyncFramesForStack(const Stack::SyncFrameOptions& options,
                                    fit::callback<void(const Err&)> callback) {
  if (options.remote_unwind) {
    return SyncFramesFromTarget(std::move(callback));
  }

  debug_ipc::ReadRegistersRequest request;
  request.categories = {debug::RegisterCategory::kGeneral};
  request.id = {.process = GetProcess()->GetKoid(), .thread = GetKoid()};

  // Request the registers that will make up the top-most stack frame. The unwinder needs these
  // for all unwinding strategies so fetching them is a prerequisite. We'll try to use local
  // debug_info before deferring to the live process for unwinding.
  session()->remote_api()->ReadRegisters(
      request, [weak_this = weak_factory_.GetWeakPtr(), cb = std::move(callback)](
                   const Err& err, debug_ipc::ReadRegistersReply reply) mutable {
        if (!weak_this) {
          return cb(Err("Thread died while fetching registers"));
        }

        if (err.has_error() || reply.registers.empty()) {
          // This commonly happens for unit tests which historically expect the frames to only be
          // available remotely and/or don't necessarily provide registers.
          return weak_this->SyncFramesFromTarget(std::move(cb));
        }

        if (weak_this->GetProcess()->GetSymbolStatus() == Process::SymbolStatus::kInProgress) {
          // The unwinder requires debuginfo to be present to unwind on the host. If there is a
          // download in progress we have to wait until the download is finished before
          // continuing.
          return weak_this->session()->system().AddPostDownloadTask(
              [weak_this, regs = reply.registers, cb = std::move(cb)]() mutable {
                if (!weak_this) {
                  return cb(Err("Thread disappeared while waiting for downloads!"));
                }

                weak_this->UnwindWithRegisters(
                    debug_ipc::ConvertRegisters(weak_this->session()->arch(), regs), std::move(cb));
              });
        }

        weak_this->UnwindWithRegisters(
            debug_ipc::ConvertRegisters(weak_this->session()->arch(), reply.registers),
            std::move(cb));
      });
}

void ThreadImpl::UnwindWithRegisters(unwinder::Registers regs, fit::callback<void(const Err&)> cb) {
  std::vector<debug_ipc::StackFrame> frames;

  auto loaded_modules = GetProcess()->GetSymbols()->GetLoadedModuleSymbols();

  std::vector<unwinder::Module> modules;
  modules.reserve(loaded_modules.size());
  std::vector<std::unique_ptr<unwinder::Memory>> unwinder_memory;
  unwinder_memory.reserve(loaded_modules.size());

  for (const auto& loaded_module : loaded_modules) {
    auto build_id_entry = session()->system().GetSymbols()->build_id_index().EntryForBuildID(
        loaded_module->build_id());

    // It's unlikely, but possible that the (likely stripped) binary file has some debug sections
    // present, so we should use the ElfMemoryRegion object which knows how to decompress debug
    // sections when that's enabled.
    std::unique_ptr<ElfMemoryRegion> binary_file_memory = nullptr;
    std::unique_ptr<ElfMemoryRegion> debug_info_file_memory = nullptr;
    if (!build_id_entry.binary.empty()) {
      binary_file_memory =
          std::make_unique<ElfMemoryRegion>(loaded_module->load_address(), build_id_entry.binary);
    }

    if (!build_id_entry.debug_info.empty()) {
      debug_info_file_memory = std::make_unique<ElfMemoryRegion>(loaded_module->load_address(),
                                                                 build_id_entry.debug_info);
    }

    modules.emplace_back(loaded_module->load_address(), binary_file_memory.get(),
                         debug_info_file_memory.get(), unwinder::Module::AddressMode::kFile);

    unwinder_memory.push_back(std::move(binary_file_memory));
    unwinder_memory.push_back(std::move(debug_info_file_memory));
  }

  // This probably doesn't need to be configurable, when someone types "bt" or "frame", they
  // want to see the whole stack, and the PrettyStackManager already does a good job of
  // removing the less helpful frames. For right now this matches what DebugAgent sends to
  // the unwinder for remote unwinds.
  constexpr size_t kMaxDepth = 256;

  // Here we try unwinding using local debug info before deferring to the target. This lets us use
  // potentially better .debug_frame section that is not loaded in the target executable, if
  // present, or deal with cases where the .eh_frame section has been stripped from the target but
  // remains in an unstripped binary that we have access to on the host.
  auto unwinder = std::make_unique<unwinder::AsyncUnwinder>(modules);
  unwinder->Unwind(
      GetProcess(), regs, kMaxDepth,
      // Move the unwinder itself and the memory into the callback so they stay alive for the
      // duration of unwinding.
      // In the typical case the reference counts for the unwinder drops to zero once unwinding
      // completes and the `fit::callback` is invoked, since `fit::callback`'s destructor is
      // automatically called after it's invoked once.
      //
      // TODO(https://fxbug.dev/454693056): Investigate the following:
      // In a rare case that the process is killed while in the process of unwinding, this
      // callback might not be invoked -- which we're not certain of, due to the handling of
      // `!weak_this` below -- leading to a memory leak since `AsyncUnwinder::on_done_` and
      // `AsyncUnwinder::this` will now hold cyclic references to each other. However, even if
      // were was the case, this actually isn't such a huge deal since:
      //  a. This scenario is extremely unlikely.
      //  b. Even if this were to happen, developers typically debug one process per zxdb session,
      //     causing zxdb to exit after the process dies.
      //  c. Even if this were not the case, this memory leak would not cost a significant amount
      //  of
      //     memory on the developer's host machine.
      [weak_this = weak_factory_.GetWeakPtr(), cb = std::move(cb), unwinder = std::move(unwinder),
       unwinder_memory =
           std::move(unwinder_memory)](std::vector<unwinder::Frame> unwinder_frames) mutable {
        // The unwinder's asynchronous API calls all callbacks reentrantly, so post a
        // task to the message loop to make sure we don't blow our own stack.
        debug::MessageLoop::Current()->PostTask(
            FROM_HERE, [weak_this, unwinder_frames = std::move(unwinder_frames),
                        cb = std::move(cb)]() mutable {
              if (!weak_this) {
                if (cb) {
                  cb(Err("Thread died during unwinding."));
                }

                return;
              }

              // If something went wrong, the last frame will have an error condition.
              // In the typical unwinding termination case, the error is cleared.
              if (unwinder_frames.back().error.has_err()) {
                weak_this->SyncFramesFromTarget(std::move(cb));
                return;
              }

              weak_this->stack_.SetFrames(debug_ipc::ThreadRecord::StackAmount::kFull,
                                          debug_ipc::ConvertFrames(unwinder_frames));

              if (cb) {
                cb(Err());
              }
            });
      });
}

void ThreadImpl::SyncFramesFromTarget(fit::callback<void(const Err&)> callback) {
  debug_ipc::ThreadStatusRequest request;
  request.id = {.process = process_->GetKoid(), .thread = koid_};

  session()->remote_api()->ThreadStatus(
      request, [callback = std::move(callback), thread = weak_factory_.GetWeakPtr()](
                   const Err& err, debug_ipc::ThreadStatusReply reply) mutable {
        if (!thread) {
          callback(Err("Thread destroyed."));
          return;
        }

        if (err.has_error()) {
          callback(err);
          return;
        }

        thread->SetMetadata(reply.record);
        callback(Err());
      });
}

std::unique_ptr<Frame> ThreadImpl::MakeFrameForStack(const debug_ipc::StackFrame& input,
                                                     Location location) {
  return std::make_unique<FrameImpl>(this, input, std::move(location));
}

Location ThreadImpl::GetSymbolizedLocationForAddress(uint64_t address) {
  auto vect = GetProcess()->GetSymbols()->ResolveInputLocation(InputLocation(address), {});

  // Symbolizing an address should always give exactly one result.
  FX_DCHECK(vect.size() == 1u);
  return vect[0];
}

void ThreadImpl::DidUpdateStackFrames() {
  if (allow_notifications_) {
    for (auto& observer : session()->thread_observers()) {
      observer.DidUpdateStackFrames(this);
    }
  }
}

void ThreadImpl::ClearState() {
  current_stop_info_ = std::nullopt;
  state_ = std::nullopt;
  blocked_reason_ = debug_ipc::ThreadRecord::BlockedReason::kNotBlocked;
  stack_.ClearFrames();
}

void ThreadImpl::RunNextPostStopTaskOrNotify(const StopInfo& info, bool should_stop,
                                             bool should_forward) {
  // It's possible that the user is typing "pause" or "continue" during any asynchronous tasks
  // so the thread state doesn't match what we thought it was. Even though we haven't sent the
  // notifications, things still could have happened.
  //
  // Therefore, we don't do anything if the thread has started running from underneath us (it
  // should always be stopped when the thread controllers are notified unless the user has done
  // something), and cancel other pending stop tasks.
  //
  // The other half of the race condition is user has requested a manual stop while we were
  // processing these post-stop tasks and we shouldn't continue it. This needs extra logic to
  // detect.
  //
  // TODO(https://fxbug.dev/42160760) don't automatically continue if the user has stopped the
  // thread.
  if (state_ == debug_ipc::ThreadRecord::State::kRunning) {
    post_stop_tasks_.clear();
    return;
  }

  bool debug_stepping = settings().GetBool(ClientSettings::Thread::kDebugStepping);

  if (post_stop_tasks_.empty()) {
    // No post-stop tasks left to run, dispatch the stop notification or continue.
    if (should_stop) {
      current_stop_info_ = info;
      // Stay stopped and notify the observers.
      if (debug_stepping)
        printf(" → Dispatching stop notification.\r\n");
      if (allow_notifications_) {
        for (auto& observer : session()->thread_observers()) {
          observer.OnThreadStopped(this, info);
        }
      }
    } else {
      // Controllers all say to continue.
      if (debug_stepping)
        printf(" → Sending continue request.\r\n");
      Continue(should_forward);
    }
  } else {
    // Run the next post-stop task.
    PostStopTask task = std::move(post_stop_tasks_.front());
    post_stop_tasks_.pop_front();
    task(fit::defer_callback(
        [weak_this = weak_factory_.GetWeakPtr(), info, should_stop, should_forward]() mutable {
          if (weak_this)
            weak_this->RunNextPostStopTaskOrNotify(info, should_stop, should_forward);
        }));
  }
}

}  // namespace zxdb
