brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.2 KiB · 100173b Raw
146 lines · cpp
1//===-- RestartRequestHandler.cpp -----------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "DAP.h"10#include "EventHelper.h"11#include "JSONUtils.h"12#include "LLDBUtils.h"13#include "Protocol/ProtocolRequests.h"14#include "RequestHandler.h"15#include "llvm/Support/JSON.h"16#include "llvm/Support/raw_ostream.h"17 18namespace lldb_dap {19 20// "RestartRequest": {21//   "allOf": [ { "$ref": "#/definitions/Request" }, {22//     "type": "object",23//     "description": "Restarts a debug session. Clients should only call this24//     request if the corresponding capability `supportsRestartRequest` is25//     true.\nIf the capability is missing or has the value false, a typical26//     client emulates `restart` by terminating the debug adapter first and then27//     launching it anew.",28//     "properties": {29//       "command": {30//         "type": "string",31//         "enum": [ "restart" ]32//       },33//       "arguments": {34//         "$ref": "#/definitions/RestartArguments"35//       }36//     },37//     "required": [ "command" ]38//   }]39// },40// "RestartArguments": {41//   "type": "object",42//   "description": "Arguments for `restart` request.",43//   "properties": {44//     "arguments": {45//       "oneOf": [46//         { "$ref": "#/definitions/LaunchRequestArguments" },47//         { "$ref": "#/definitions/AttachRequestArguments" }48//       ],49//       "description": "The latest version of the `launch` or `attach`50//       configuration."51//     }52//   }53// },54// "RestartResponse": {55//   "allOf": [ { "$ref": "#/definitions/Response" }, {56//     "type": "object",57//     "description": "Response to `restart` request. This is just an58//     acknowledgement, so no body field is required."59//   }]60// },61void RestartRequestHandler::operator()(62    const llvm::json::Object &request) const {63  llvm::json::Object response;64  FillResponse(request, response);65  if (!dap.target.GetProcess().IsValid()) {66    response["success"] = llvm::json::Value(false);67    EmplaceSafeString(response, "message",68                      "Restart request received but no process was launched.");69    dap.SendJSON(llvm::json::Value(std::move(response)));70    return;71  }72 73  const llvm::json::Object *arguments = request.getObject("arguments");74  if (arguments) {75    // The optional `arguments` field in RestartRequest can contain an updated76    // version of the launch arguments. If there's one, use it.77    if (const llvm::json::Value *restart_arguments =78            arguments->get("arguments")) {79      protocol::LaunchRequestArguments updated_arguments;80      llvm::json::Path::Root root;81      if (!fromJSON(*restart_arguments, updated_arguments, root)) {82        response["success"] = llvm::json::Value(false);83        EmplaceSafeString(84            response, "message",85            llvm::formatv("Failed to parse updated launch arguments: {0}",86                          llvm::toString(root.getError()))87                .str());88        dap.SendJSON(llvm::json::Value(std::move(response)));89        return;90      }91      dap.last_launch_request = updated_arguments;92      // Update DAP configuration based on the latest copy of the launch93      // arguments.94      dap.SetConfiguration(updated_arguments.configuration, false);95      dap.ConfigureSourceMaps();96    }97  }98 99  // Keep track of the old PID so when we get a "process exited" event from the100  // killed process we can detect it and not shut down the whole session.101  lldb::SBProcess process = dap.target.GetProcess();102  dap.restarting_process_id = process.GetProcessID();103 104  // Stop the current process if necessary. The logic here is similar to105  // CommandObjectProcessLaunchOrAttach::StopProcessIfNecessary, except that106  // we don't ask the user for confirmation.107  if (process.IsValid()) {108    ScopeSyncMode scope_sync_mode(dap.debugger);109    lldb::StateType state = process.GetState();110    if (state != lldb::eStateConnected) {111      process.Kill();112    }113    // Clear the list of thread ids to avoid sending "thread exited" events114    // for threads of the process we are terminating.115    dap.thread_ids.clear();116  }117 118  // FIXME: Should we run 'preRunCommands'?119  // FIXME: Should we add a 'preRestartCommands'?120  if (llvm::Error err = LaunchProcess(*dap.last_launch_request)) {121    response["success"] = llvm::json::Value(false);122    EmplaceSafeString(response, "message", llvm::toString(std::move(err)));123    dap.SendJSON(llvm::json::Value(std::move(response)));124    return;125  }126 127  SendProcessEvent(dap, Launch);128 129  // This is normally done after receiving a "configuration done" request.130  // Because we're restarting, configuration has already happened so we can131  // continue the process right away.132  if (dap.stop_at_entry) {133    if (llvm::Error err = SendThreadStoppedEvent(dap, /*on_entry=*/true)) {134      EmplaceSafeString(response, "message", llvm::toString(std::move(err)));135      dap.SendJSON(llvm::json::Value(std::move(response)));136      return;137    }138  } else {139    dap.target.GetProcess().Continue();140  }141 142  dap.SendJSON(llvm::json::Value(std::move(response)));143}144 145} // namespace lldb_dap146