wallace updated this revision to Diff 314151. wallace added a comment. Herald added a subscriber: JDevlieghere.
nit Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D93951/new/ https://reviews.llvm.org/D93951 Files: lldb/test/API/tools/lldb-vscode/runInTerminal/TestVSCode_runInTerminal.py lldb/tools/lldb-vscode/JSONUtils.cpp lldb/tools/lldb-vscode/JSONUtils.h lldb/tools/lldb-vscode/Options.td lldb/tools/lldb-vscode/VSCode.h lldb/tools/lldb-vscode/lldb-vscode.cpp
Index: lldb/tools/lldb-vscode/lldb-vscode.cpp =================================================================== --- lldb/tools/lldb-vscode/lldb-vscode.cpp +++ lldb/tools/lldb-vscode/lldb-vscode.cpp @@ -1441,6 +1441,47 @@ g_vsc.SendJSON(llvm::json::Value(std::move(response))); } +std::string CreateRunInTerminalPidFile() { + llvm::SmallString<256> temp_file; + if (std::error_code EC = llvm::sys::fs::getPotentiallyUniqueTempFileName( + "lldb-vscode-run-in-terminal", "pid", temp_file)) { + llvm::errs() << "Error making unique filename: " << EC.message() << "!\n"; + exit(1); + } + std::string pid_file = temp_file.str().str(); + // We'll use a fifo file to communicate the target's pid with the debug + // adaptor. +#if !defined(_WIN32) + if (int err = mkfifo(pid_file.c_str(), 0666)) { + perror("mkfifo failed"); + exit(1); + } +#endif + return pid_file; +} + +void CleanUpRunInTerminalPidFile(const std::string &pid_file) { +#if !defined(_WIN32) + unlink(pid_file.c_str()); +#endif +} + +lldb::pid_t GetRunInTerminalDebuggeePid(const std::string &pid_file) { + lldb::pid_t pid; + std::ifstream pid_file_reader(pid_file, std::ifstream::in); + pid_file_reader >> pid; + return pid; +} + +void NotifyRunInTerminalDebuggeeWasAttached(const std::string &pid_file) { + // We create a file to notify the debuggee that we attached. + std::ofstream did_attach_file(pid_file + ".attached"); +} + +bool RunInTerminalDebugeeWasAttached(const std::string &pid_file) { + return llvm::sys::fs::exists(pid_file + ".attached"); +} + void request_runInTerminal(const llvm::json::Object &launch_request, llvm::json::Object &launch_response) { // We have already created a target that has a valid "program" path to the @@ -1449,11 +1490,12 @@ g_vsc.is_attach = true; lldb::SBAttachInfo attach_info; lldb::SBError error; - attach_info.SetWaitForLaunch(true, /*async*/ true); - g_vsc.target.Attach(attach_info, error); - llvm::json::Object reverse_request = - CreateRunInTerminalReverseRequest(launch_request); + // The debuggee will write its pid to this file + std::string pid_file = CreateRunInTerminalPidFile(); + + llvm::json::Object reverse_request = CreateRunInTerminalReverseRequest( + launch_request, g_vsc.debug_adaptor_path, pid_file); llvm::json::Object reverse_response; lldb_vscode::PacketStatus status = g_vsc.SendReverseRequest(reverse_request, reverse_response); @@ -1461,24 +1503,32 @@ error.SetErrorString("Process cannot be launched by IDE."); if (error.Success()) { - // Wait for the attach stop event to happen or for a timeout. - g_vsc.waiting_for_run_in_terminal = true; - static std::mutex mutex; - std::unique_lock<std::mutex> locker(mutex); - g_vsc.request_in_terminal_cv.wait_for(locker, std::chrono::seconds(10)); + lldb::pid_t pid = GetRunInTerminalDebuggeePid(pid_file); + attach_info.SetProcessID(pid); + + g_vsc.debugger.SetAsync(false); + g_vsc.target.Attach(attach_info, error); auto attached_pid = g_vsc.target.GetProcess().GetProcessID(); if (attached_pid == LLDB_INVALID_PROCESS_ID) error.SetErrorString("Failed to attach to a process"); - else - SendProcessEvent(Attach); + else { + NotifyRunInTerminalDebuggeeWasAttached(pid_file); + // We resume the process to let stopOnEntry decide whether to stop the + // process or not. + g_vsc.target.GetProcess().Continue(); + } + g_vsc.debugger.SetAsync(true); } + CleanUpRunInTerminalPidFile(pid_file); + if (error.Fail()) { launch_response["success"] = llvm::json::Value(false); EmplaceSafeString(launch_response, "message", std::string(error.GetCString())); } else { + SendProcessEvent(Attach); launch_response["success"] = llvm::json::Value(true); g_vsc.SendJSON(CreateEventObject("initialized")); } @@ -1556,12 +1606,6 @@ return; } - if (GetBoolean(arguments, "runInTerminal", false)) { - request_runInTerminal(request, response); - g_vsc.SendJSON(llvm::json::Value(std::move(response))); - return; - } - // Instantiate a launch info instance for the target. auto launch_info = g_vsc.target.GetLaunchInfo(); @@ -1597,6 +1641,13 @@ // Run any pre run LLDB commands the user specified in the launch.json g_vsc.RunPreRunCommands(); + + if (GetBoolean(arguments, "runInTerminal", false)) { + request_runInTerminal(request, response); + g_vsc.SendJSON(llvm::json::Value(std::move(response))); + return; + } + if (launchCommands.empty()) { // Disable async events so the launch will be successful when we return from // the launch call and the launch will happen synchronously @@ -2949,6 +3000,36 @@ } int main(int argc, char *argv[]) { + g_vsc.debug_adaptor_path = argv[0]; + + LLDBVSCodeOptTable T; + unsigned MAI, MAC; + llvm::ArrayRef<const char *> ArgsArr = llvm::makeArrayRef(argv + 1, argc); + llvm::opt::InputArgList input_args = T.ParseArgs(ArgsArr, MAI, MAC); + +#if !defined(_WIN32) + if (auto *target_arg = input_args.getLastArg(OPT_launch_target)) { + std::string pid_file = input_args.getLastArg(OPT_pid_file)->getValue(); + std::ofstream pid_file_writer(pid_file, std::ofstream::out); + pid_file_writer << getpid() << std::endl; + pid_file_writer.close(); + + // 20 seconds waiting to be attached. We don't wait indefinitely using a + // signal to prevent being paused forever. + for (int i = 0; i < 2000; i++) { + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + if (RunInTerminalDebugeeWasAttached(pid_file)) { + const char *target = target_arg->getValue(); + execv(target, argv + target_arg->getIndex() + 2); + perror("Couldn't launch target"); + exit(EXIT_FAILURE); + } + } + + llvm::outs() << "lldb-vscode didn't attach to this process"; + exit(EXIT_FAILURE); + } +#endif // Initialize LLDB first before we do anything. lldb::SBDebugger::Initialize(); @@ -2957,11 +3038,6 @@ int portno = -1; - LLDBVSCodeOptTable T; - unsigned MAI, MAC; - llvm::ArrayRef<const char *> ArgsArr = llvm::makeArrayRef(argv + 1, argc); - llvm::opt::InputArgList input_args = T.ParseArgs(ArgsArr, MAI, MAC); - if (input_args.hasArg(OPT_help)) { printHelp(T, llvm::sys::path::filename(argv[0])); return 0; Index: lldb/tools/lldb-vscode/VSCode.h =================================================================== --- lldb/tools/lldb-vscode/VSCode.h +++ lldb/tools/lldb-vscode/VSCode.h @@ -77,6 +77,7 @@ }; struct VSCode { + std::string debug_adaptor_path; InputStream input; OutputStream output; lldb::SBDebugger debugger; Index: lldb/tools/lldb-vscode/Options.td =================================================================== --- lldb/tools/lldb-vscode/Options.td +++ lldb/tools/lldb-vscode/Options.td @@ -23,3 +23,20 @@ def: Separate<["-"], "p">, Alias<port>, HelpText<"Alias for --port">; + +def launch_target: Separate<["--", "-"], "launch-target">, + MetaVarName<"<target>">, + HelpText<"Launch a target for the launchInTerminal request. Any argument " + "provided after this one will be passed to the target. The parameter " + "--pid-file must also be specified.">; +def: Separate<["-"], "t">, + Alias<launch_target>, + HelpText<"Alias for --launch-target">; + +def pid_file: Separate<["--", "-"], "pid-file">, + MetaVarName<"<pid-file>">, + HelpText<"File to write the pid of the target launched with the " + "--launch-target option.">; +def: Separate<["-"], "f">, + Alias<pid_file>, + HelpText<"Alias for --pid-file">; Index: lldb/tools/lldb-vscode/JSONUtils.h =================================================================== --- lldb/tools/lldb-vscode/JSONUtils.h +++ lldb/tools/lldb-vscode/JSONUtils.h @@ -449,11 +449,20 @@ /// The original launch_request object whose fields are used to construct /// the reverse request object. /// +/// \param[in] debug_adaptor_path +/// Path to the current debug adaptor. It will be used to delegate the +/// launch of the target. +/// +/// \param[in] pid_file +/// A file that will be used to communicate the pid of the debuggee. +/// /// \return /// A "runInTerminal" JSON object that follows the specification outlined by /// Microsoft. llvm::json::Object -CreateRunInTerminalReverseRequest(const llvm::json::Object &launch_request); +CreateRunInTerminalReverseRequest(const llvm::json::Object &launch_request, + llvm::StringRef debug_adaptor_path, + llvm::StringRef pid_file); } // namespace lldb_vscode Index: lldb/tools/lldb-vscode/JSONUtils.cpp =================================================================== --- lldb/tools/lldb-vscode/JSONUtils.cpp +++ lldb/tools/lldb-vscode/JSONUtils.cpp @@ -1001,7 +1001,9 @@ /// See /// https://microsoft.github.io/debug-adapter-protocol/specification#Reverse_Requests_RunInTerminal llvm::json::Object -CreateRunInTerminalReverseRequest(const llvm::json::Object &launch_request) { +CreateRunInTerminalReverseRequest(const llvm::json::Object &launch_request, + llvm::StringRef debug_adaptor_path, + llvm::StringRef pid_file) { llvm::json::Object reverse_request; reverse_request.try_emplace("type", "request"); reverse_request.try_emplace("command", "runInTerminal"); @@ -1012,10 +1014,13 @@ run_in_terminal_args.try_emplace("kind", "integrated"); auto launch_request_arguments = launch_request.getObject("arguments"); - std::vector<std::string> args = GetStrings(launch_request_arguments, "args"); // The program path must be the first entry in the "args" field - args.insert(args.begin(), - GetString(launch_request_arguments, "program").str()); + std::vector<std::string> args = { + debug_adaptor_path.str(), "-f", pid_file.str(), "-t", + GetString(launch_request_arguments, "program").str()}; + std::vector<std::string> target_args = + GetStrings(launch_request_arguments, "args"); + args.insert(args.end(), target_args.begin(), target_args.end()); run_in_terminal_args.try_emplace("args", args); const auto cwd = GetString(launch_request_arguments, "cwd"); Index: lldb/test/API/tools/lldb-vscode/runInTerminal/TestVSCode_runInTerminal.py =================================================================== --- lldb/test/API/tools/lldb-vscode/runInTerminal/TestVSCode_runInTerminal.py +++ lldb/test/API/tools/lldb-vscode/runInTerminal/TestVSCode_runInTerminal.py @@ -17,7 +17,7 @@ mydir = TestBase.compute_mydir(__file__) - @skipUnlessDarwin + @skipIfWindows @skipIfRemote def test_runInTerminal(self): '''
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits