This patch migrates `restart` request to structured types. Also, I added some checks that at least one of the required fields was provided for `launch` and `attach` requests. Maybe I missed some possible configurations, so please double check.
80 lines
3.0 KiB
C++
80 lines
3.0 KiB
C++
//===-- RestartRequestHandler.cpp -----------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "DAP.h"
|
|
#include "DAPError.h"
|
|
#include "EventHelper.h"
|
|
#include "LLDBUtils.h"
|
|
#include "Protocol/ProtocolRequests.h"
|
|
#include "RequestHandler.h"
|
|
|
|
using namespace lldb_dap;
|
|
using namespace lldb_dap::protocol;
|
|
|
|
/// Restarts a debug session. Clients should only call this request if the
|
|
/// corresponding capability `supportsRestartRequest` is true.
|
|
/// If the capability is missing or has the value false, a typical client
|
|
/// emulates `restart` by terminating the debug adapter first and then launching
|
|
/// it anew.
|
|
llvm::Error
|
|
RestartRequestHandler::Run(const std::optional<RestartArguments> &args) const {
|
|
if (!dap.target.GetProcess().IsValid())
|
|
return llvm::make_error<DAPError>(
|
|
"Restart request received but no process was launched.");
|
|
|
|
if (args) {
|
|
if (std::holds_alternative<AttachRequestArguments>(args->arguments))
|
|
return llvm::make_error<DAPError>(
|
|
"Restarting an AttachRequest is not supported.");
|
|
if (const auto *arguments =
|
|
std::get_if<LaunchRequestArguments>(&args->arguments);
|
|
arguments) {
|
|
dap.last_launch_request = *arguments;
|
|
// Update DAP configuration based on the latest copy of the launch
|
|
// arguments.
|
|
dap.SetConfiguration(arguments->configuration, false);
|
|
dap.ConfigureSourceMaps();
|
|
}
|
|
}
|
|
|
|
// Keep track of the old PID so when we get a "process exited" event from the
|
|
// killed process we can detect it and not shut down the whole session.
|
|
lldb::SBProcess process = dap.target.GetProcess();
|
|
dap.restarting_process_id = process.GetProcessID();
|
|
|
|
// Stop the current process if necessary. The logic here is similar to
|
|
// CommandObjectProcessLaunchOrAttach::StopProcessIfNecessary, except that
|
|
// we don't ask the user for confirmation.
|
|
if (process.IsValid()) {
|
|
ScopeSyncMode scope_sync_mode(dap.debugger);
|
|
lldb::StateType state = process.GetState();
|
|
if (state != lldb::eStateConnected) {
|
|
if (lldb::SBError error = process.Kill(); error.Fail())
|
|
return ToError(error);
|
|
}
|
|
// Clear the list of thread ids to avoid sending "thread exited" events
|
|
// for threads of the process we are terminating.
|
|
dap.thread_ids.clear();
|
|
}
|
|
|
|
// FIXME: Should we run 'preRunCommands'?
|
|
// FIXME: Should we add a 'preRestartCommands'?
|
|
if (llvm::Error error = LaunchProcess(*dap.last_launch_request))
|
|
return error;
|
|
|
|
SendProcessEvent(dap, Launch);
|
|
|
|
// This is normally done after receiving a "configuration done" request.
|
|
// Because we're restarting, configuration has already happened so we can
|
|
// continue the process right away.
|
|
if (dap.stop_at_entry)
|
|
return SendThreadStoppedEvent(dap, /*on_entry=*/true);
|
|
|
|
return ToError(dap.target.GetProcess().Continue());
|
|
}
|