https://github.com/DrSergei created 
https://github.com/llvm/llvm-project/pull/138160

Added `runInTerminal` support for Windows based on Windows Named Pipes. Adapted 
existed `FifoFile` class to Windows client-server pipes model. When server side 
owns the assosieted filesystem handle and client side only provide read-write 
acces to it. Also, fixed small typo in `JSONUtill.cpp` related to 
`runInTerminal` functionality.

>From c60a556561b70f8eab0781e5de9374aac87529d4 Mon Sep 17 00:00:00 2001
From: Druzhkov Sergei <serzhdruz...@gmail.com>
Date: Thu, 1 May 2025 18:46:22 +0300
Subject: [PATCH] [lldb-dap] Add runInTerminal support for Windows

---
 .../runInTerminal/TestDAP_runInTerminal.py    |  3 -
 lldb/tools/lldb-dap/FifoFiles.cpp             | 85 +++++++++++++++++--
 lldb/tools/lldb-dap/FifoFiles.h               | 36 ++++++--
 .../tools/lldb-dap/Handler/RequestHandler.cpp | 12 ++-
 lldb/tools/lldb-dap/JSONUtils.cpp             |  2 +-
 lldb/tools/lldb-dap/RunInTerminal.cpp         | 34 ++++++--
 lldb/tools/lldb-dap/RunInTerminal.h           | 29 ++++++-
 lldb/tools/lldb-dap/lldb-dap.cpp              | 72 ++++++++++++++--
 8 files changed, 237 insertions(+), 36 deletions(-)

diff --git 
a/lldb/test/API/tools/lldb-dap/runInTerminal/TestDAP_runInTerminal.py 
b/lldb/test/API/tools/lldb-dap/runInTerminal/TestDAP_runInTerminal.py
index 9aab7ca3293db..d5355f3bacd9c 100644
--- a/lldb/test/API/tools/lldb-dap/runInTerminal/TestDAP_runInTerminal.py
+++ b/lldb/test/API/tools/lldb-dap/runInTerminal/TestDAP_runInTerminal.py
@@ -43,7 +43,6 @@ def isTestSupported(self):
         except:
             return False
 
-    @skipIfWindows
     @skipIf(oslist=["linux"], archs=no_match(["x86_64"]))
     def test_runInTerminal(self):
         if not self.isTestSupported():
@@ -113,7 +112,6 @@ def test_runInTerminalWithObjectEnv(self):
         self.assertIn("FOO", request_envs)
         self.assertEqual("BAR", request_envs["FOO"])
 
-    @skipIfWindows
     @skipIf(oslist=["linux"], archs=no_match(["x86_64"]))
     def test_runInTerminalInvalidTarget(self):
         if not self.isTestSupported():
@@ -132,7 +130,6 @@ def test_runInTerminalInvalidTarget(self):
             response["message"],
         )
 
-    @skipIfWindows
     @skipIf(oslist=["linux"], archs=no_match(["x86_64"]))
     def test_missingArgInRunInTerminalLauncher(self):
         if not self.isTestSupported():
diff --git a/lldb/tools/lldb-dap/FifoFiles.cpp 
b/lldb/tools/lldb-dap/FifoFiles.cpp
index 1f1bba80bd3b1..43eb4679b592f 100644
--- a/lldb/tools/lldb-dap/FifoFiles.cpp
+++ b/lldb/tools/lldb-dap/FifoFiles.cpp
@@ -24,26 +24,53 @@ using namespace llvm;
 
 namespace lldb_dap {
 
-FifoFile::FifoFile(StringRef path) : m_path(path) {}
+#if defined(_WIN32)
+FifoFile::FifoFile(StringRef path, HANDLE handle, bool is_server)
+    : m_path(path), m_is_server(is_server), m_pipe_fd(handle) {}
+#else
+FifoFile::FifoFile(StringRef path, bool is_server)
+    : m_path(path), m_is_server(is_server) {}
+#endif
 
 FifoFile::~FifoFile() {
-#if !defined(_WIN32)
-  unlink(m_path.c_str());
+#if defined(_WIN32)
+  if (m_pipe_fd == INVALID_HANDLE_VALUE)
+    return;
+  if (m_is_server)
+    DisconnectNamedPipe(m_pipe_fd);
+  CloseHandle(m_pipe_fd);
+#else
+  if (m_is_server)
+    unlink(m_path.c_str());
 #endif
 }
 
-Expected<std::shared_ptr<FifoFile>> CreateFifoFile(StringRef path) {
+Expected<std::shared_ptr<FifoFile>> CreateFifoFile(StringRef path,
+                                                   bool is_server) {
 #if defined(_WIN32)
-  return createStringError(inconvertibleErrorCode(), "Unimplemented");
+  if (!is_server)
+    return std::make_shared<FifoFile>(path, INVALID_HANDLE_VALUE, is_server);
+  HANDLE handle =
+      CreateNamedPipeA(path.data(), PIPE_ACCESS_DUPLEX,
+                       PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1,
+                       1024 * 16, 1024 * 16, 0, NULL);
+  if (handle == INVALID_HANDLE_VALUE)
+    return createStringError(
+        std::error_code(GetLastError(), std::generic_category()),
+        "Couldn't create fifo file: %s", path.data());
+  return std::make_shared<FifoFile>(path, handle, is_server);
 #else
+  if (!is_server)
+    return std::make_shared<FifoFile>(path, is_server);
   if (int err = mkfifo(path.data(), 0600))
     return createStringError(std::error_code(err, std::generic_category()),
                              "Couldn't create fifo file: %s", path.data());
-  return std::make_shared<FifoFile>(path);
+  return std::make_shared<FifoFile>(path, is_server);
 #endif
 }
 
-FifoFileIO::FifoFileIO(StringRef fifo_file, StringRef other_endpoint_name)
+FifoFileIO::FifoFileIO(std::shared_ptr<FifoFile> fifo_file,
+                       StringRef other_endpoint_name)
     : m_fifo_file(fifo_file), m_other_endpoint_name(other_endpoint_name) {}
 
 Expected<json::Value> FifoFileIO::ReadJSON(std::chrono::milliseconds timeout) {
@@ -52,11 +79,27 @@ Expected<json::Value> 
FifoFileIO::ReadJSON(std::chrono::milliseconds timeout) {
   std::optional<std::string> line;
   std::future<void> *future =
       new std::future<void>(std::async(std::launch::async, [&]() {
-        std::ifstream reader(m_fifo_file, std::ifstream::in);
+#if defined(_WIN32)
+        std::string buffer;
+        buffer.reserve(4096);
+        char ch;
+        DWORD bytes_read = 0;
+        while (ReadFile(m_fifo_file->m_pipe_fd, &ch, 1, &bytes_read, NULL) &&
+               (bytes_read == 1)) {
+          buffer.push_back(ch);
+          if (ch == '\n') {
+            break;
+          }
+        }
+        if (!buffer.empty())
+          line = std::move(buffer);
+#else
+        std::ifstream reader(m_fifo_file->m_path, std::ifstream::in);
         std::string buffer;
         std::getline(reader, buffer);
         if (!buffer.empty())
           line = buffer;
+#endif
       }));
   if (future->wait_for(timeout) == std::future_status::timeout || !line)
     // Indeed this is a leak, but it's intentional. "future" obj destructor
@@ -78,9 +121,19 @@ Error FifoFileIO::SendJSON(const json::Value &json,
   bool done = false;
   std::future<void> *future =
       new std::future<void>(std::async(std::launch::async, [&]() {
+#if defined(_WIN32)
+        std::string buffer = JSONToString(json);
+        buffer.append("\n");
+        DWORD bytes_write = 0;
+        WriteFile(m_fifo_file->m_pipe_fd, buffer.c_str(), buffer.size(),
+                  &bytes_write, NULL);
+        done = bytes_write == buffer.size();
+#else
+        std::ofstream writer(m_fifo_file->m_path, std::ofstream::out);
         std::ofstream writer(m_fifo_file, std::ofstream::out);
         writer << JSONToString(json) << std::endl;
         done = true;
+#endif
       }));
   if (future->wait_for(timeout) == std::future_status::timeout || !done) {
     // Indeed this is a leak, but it's intentional. "future" obj destructor 
will
@@ -98,4 +151,20 @@ Error FifoFileIO::SendJSON(const json::Value &json,
   return Error::success();
 }
 
+#if defined(_WIN32)
+bool FifoFileIO::Connect() {
+  if (m_fifo_file->m_is_server) {
+    return ConnectNamedPipe(m_fifo_file->m_pipe_fd, NULL);
+  }
+  if (!WaitNamedPipeA(m_fifo_file->m_path.c_str(), NMPWAIT_WAIT_FOREVER))
+    return false;
+  m_fifo_file->m_pipe_fd =
+      CreateFileA(m_fifo_file->m_path.c_str(), GENERIC_READ | GENERIC_WRITE, 0,
+                  NULL, OPEN_EXISTING, 0, NULL);
+  if (m_fifo_file->m_pipe_fd == INVALID_HANDLE_VALUE)
+    return false;
+  return true;
+}
+#endif
+
 } // namespace lldb_dap
diff --git a/lldb/tools/lldb-dap/FifoFiles.h b/lldb/tools/lldb-dap/FifoFiles.h
index 633ebeb2aedd4..335c7561040dd 100644
--- a/lldb/tools/lldb-dap/FifoFiles.h
+++ b/lldb/tools/lldb-dap/FifoFiles.h
@@ -12,19 +12,35 @@
 #include "llvm/Support/Error.h"
 #include "llvm/Support/JSON.h"
 
+#if defined(_WIN32)
+#include "lldb/Host/windows/windows.h"
+#endif
+
 #include <chrono>
 
 namespace lldb_dap {
 
+class FifoFileIO;
+
 /// Struct that controls the life of a fifo file in the filesystem.
 ///
 /// The file is destroyed when the destructor is invoked.
 struct FifoFile {
-  FifoFile(llvm::StringRef path);
+#if defined(_WIN32)
+  FifoFile(llvm::StringRef path, HANDLE handle, bool is_server);
+#else
+  FifoFile(llvm::StringRef path, bool is_server);
+#endif
 
   ~FifoFile();
 
   std::string m_path;
+  bool m_is_server;
+#if defined(_WIN32)
+  HANDLE m_pipe_fd = INVALID_HANDLE_VALUE;
+#endif
+
+  friend FifoFileIO;
 };
 
 /// Create a fifo file in the filesystem.
@@ -32,20 +48,26 @@ struct FifoFile {
 /// \param[in] path
 ///     The path for the fifo file.
 ///
+/// \param[in] is_server
+///     If \a is_server is true, then created instance of FifoFile will own
+///     created file.
+///
 /// \return
 ///     A \a std::shared_ptr<FifoFile> if the file could be created, or an
 ///     \a llvm::Error in case of failures.
-llvm::Expected<std::shared_ptr<FifoFile>> CreateFifoFile(llvm::StringRef path);
+llvm::Expected<std::shared_ptr<FifoFile>> CreateFifoFile(llvm::StringRef path,
+                                                         bool is_server);
 
 class FifoFileIO {
 public:
   /// \param[in] fifo_file
-  ///     The path to an input fifo file that exists in the file system.
+  ///     The std::shared_ptr<FifoFile> to an existing fifo file.
   ///
   /// \param[in] other_endpoint_name
   ///     A human readable name for the other endpoint that will communicate
   ///     using this file. This is used for error messages.
-  FifoFileIO(llvm::StringRef fifo_file, llvm::StringRef other_endpoint_name);
+  FifoFileIO(std::shared_ptr<FifoFile> fifo_file,
+             llvm::StringRef other_endpoint_name);
 
   /// Read the next JSON object from the underlying input fifo file.
   ///
@@ -75,8 +97,12 @@ class FifoFileIO {
       const llvm::json::Value &json,
       std::chrono::milliseconds timeout = std::chrono::milliseconds(20000));
 
+#if defined(_WIN32)
+  bool Connect();
+#endif
+
 private:
-  std::string m_fifo_file;
+  std::shared_ptr<FifoFile> m_fifo_file;
   std::string m_other_endpoint_name;
 };
 
diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
index 7a75cd93abc19..e68597194c296 100644
--- a/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
@@ -119,9 +119,9 @@ RunInTerminal(DAP &dap, const 
protocol::LaunchRequestArguments &arguments) {
       CreateRunInTerminalCommFile();
   if (!comm_file_or_err)
     return comm_file_or_err.takeError();
-  FifoFile &comm_file = *comm_file_or_err.get();
+  std::shared_ptr<FifoFile> comm_file = *comm_file_or_err;
 
-  RunInTerminalDebugAdapterCommChannel comm_channel(comm_file.m_path);
+  RunInTerminalDebugAdapterCommChannel comm_channel(comm_file);
 
   lldb::pid_t debugger_pid = LLDB_INVALID_PROCESS_ID;
 #if !defined(_WIN32)
@@ -130,10 +130,16 @@ RunInTerminal(DAP &dap, const 
protocol::LaunchRequestArguments &arguments) {
 
   llvm::json::Object reverse_request = CreateRunInTerminalReverseRequest(
       *arguments.configuration.program, arguments.args, arguments.env,
-      arguments.cwd.value_or(""), comm_file.m_path, debugger_pid);
+      arguments.cwd.value_or(""), comm_file->m_path, debugger_pid);
   dap.SendReverseRequest<LogFailureResponseHandler>("runInTerminal",
                                                     
std::move(reverse_request));
 
+#if defined(_WIN32)
+  if (!comm_channel.Connect())
+    return llvm::createStringError(llvm::inconvertibleErrorCode(),
+                                   "Failed to connect to the named pipe.");
+#endif
+
   if (llvm::Expected<lldb::pid_t> pid = comm_channel.GetLauncherPid())
     attach_info.SetProcessID(*pid);
   else
diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp 
b/lldb/tools/lldb-dap/JSONUtils.cpp
index 4409cf5b27e5b..f29ab09e4feb9 100644
--- a/lldb/tools/lldb-dap/JSONUtils.cpp
+++ b/lldb/tools/lldb-dap/JSONUtils.cpp
@@ -1463,7 +1463,7 @@ llvm::json::Object CreateRunInTerminalReverseRequest(
   req_args.push_back("--launch-target");
   req_args.push_back(program.str());
   req_args.insert(req_args.end(), args.begin(), args.end());
-  run_in_terminal_args.try_emplace("args", args);
+  run_in_terminal_args.try_emplace("args", req_args);
 
   if (!cwd.empty())
     run_in_terminal_args.try_emplace("cwd", cwd);
diff --git a/lldb/tools/lldb-dap/RunInTerminal.cpp 
b/lldb/tools/lldb-dap/RunInTerminal.cpp
index 9f309dd78221a..8afe6e8907710 100644
--- a/lldb/tools/lldb-dap/RunInTerminal.cpp
+++ b/lldb/tools/lldb-dap/RunInTerminal.cpp
@@ -9,7 +9,9 @@
 #include "RunInTerminal.h"
 #include "JSONUtils.h"
 
-#if !defined(_WIN32)
+#if defined(_WIN32)
+#include "lldb/Host/windows/windows.h"
+#else
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
@@ -96,7 +98,7 @@ static Error ToError(const RunInTerminalMessage &message) {
 }
 
 RunInTerminalLauncherCommChannel::RunInTerminalLauncherCommChannel(
-    StringRef comm_file)
+    std::shared_ptr<FifoFile> comm_file)
     : m_io(comm_file, "debug adapter") {}
 
 Error RunInTerminalLauncherCommChannel::WaitUntilDebugAdapterAttaches(
@@ -111,8 +113,8 @@ Error 
RunInTerminalLauncherCommChannel::WaitUntilDebugAdapterAttaches(
     return message.takeError();
 }
 
-Error RunInTerminalLauncherCommChannel::NotifyPid() {
-  return m_io.SendJSON(RunInTerminalMessagePid(getpid()).ToJSON());
+Error RunInTerminalLauncherCommChannel::NotifyPid(lldb::pid_t pid) {
+  return m_io.SendJSON(RunInTerminalMessagePid(pid).ToJSON());
 }
 
 void RunInTerminalLauncherCommChannel::NotifyError(StringRef error) {
@@ -121,8 +123,12 @@ void 
RunInTerminalLauncherCommChannel::NotifyError(StringRef error) {
     llvm::errs() << llvm::toString(std::move(err)) << "\n";
 }
 
+#if defined(_WIN32)
+bool RunInTerminalLauncherCommChannel::Connect() { return m_io.Connect(); }
+#endif
+
 RunInTerminalDebugAdapterCommChannel::RunInTerminalDebugAdapterCommChannel(
-    StringRef comm_file)
+    std::shared_ptr<FifoFile> comm_file)
     : m_io(comm_file, "runInTerminal launcher") {}
 
 // Can't use \a std::future<llvm::Error> because it doesn't compile on Windows
@@ -148,6 +154,10 @@ Expected<lldb::pid_t> 
RunInTerminalDebugAdapterCommChannel::GetLauncherPid() {
   }
 }
 
+#if defined(_WIN32)
+bool RunInTerminalDebugAdapterCommChannel::Connect() { return m_io.Connect(); }
+#endif
+
 std::string RunInTerminalDebugAdapterCommChannel::GetLauncherError() {
   // We know there's been an error, so a small timeout is enough.
   if (Expected<RunInTerminalMessageUP> message =
@@ -158,13 +168,25 @@ std::string 
RunInTerminalDebugAdapterCommChannel::GetLauncherError() {
 }
 
 Expected<std::shared_ptr<FifoFile>> CreateRunInTerminalCommFile() {
+#if defined(_WIN32)
+  static constexpr llvm::StringLiteral g_pipe_name_prefix = "\\\\.\\Pipe\\";
+  SmallString<256> comm_file;
+  sys::fs::createUniquePath("lldb-dap-run-in-terminal-comm-%%%%%%", comm_file,
+                            +false);
+  return CreateFifoFile((g_pipe_name_prefix + comm_file.str()).str(), true);
+#else
   SmallString<256> comm_file;
   if (std::error_code EC = sys::fs::getPotentiallyUniqueTempFileName(
           "lldb-dap-run-in-terminal-comm", "", comm_file))
     return createStringError(EC, "Error making unique file name for "
                                  "runInTerminal communication files");
+  return CreateFifoFile(comm_file.str(), true);
+#endif
+}
 
-  return CreateFifoFile(comm_file.str());
+Expected<std::shared_ptr<FifoFile>>
+OpenRunInTerminalCommFile(llvm::StringRef fifo_file) {
+  return CreateFifoFile(fifo_file, false);
 }
 
 } // namespace lldb_dap
diff --git a/lldb/tools/lldb-dap/RunInTerminal.h 
b/lldb/tools/lldb-dap/RunInTerminal.h
index 457850c8ea538..10e715d1d12e1 100644
--- a/lldb/tools/lldb-dap/RunInTerminal.h
+++ b/lldb/tools/lldb-dap/RunInTerminal.h
@@ -70,7 +70,7 @@ struct RunInTerminalMessageDidAttach : RunInTerminalMessage {
 
 class RunInTerminalLauncherCommChannel {
 public:
-  RunInTerminalLauncherCommChannel(llvm::StringRef comm_file);
+  RunInTerminalLauncherCommChannel(std::shared_ptr<FifoFile> comm_file);
 
   /// Wait until the debug adapter attaches.
   ///
@@ -82,23 +82,31 @@ class RunInTerminalLauncherCommChannel {
   ///     out.
   llvm::Error WaitUntilDebugAdapterAttaches(std::chrono::milliseconds timeout);
 
-  /// Notify the debug adapter this process' pid.
+  /// Notify the debug adaptor debuggee's  pid.
+  ///
+  /// \param[in] pid
+  ///    The process ID to be attached.
   ///
   /// \return
   ///     An \a llvm::Error object in case of errors or if this operation times
   ///     out.
-  llvm::Error NotifyPid();
+  llvm::Error NotifyPid(lldb::pid_t pid);
 
   /// Notify the debug adapter that there's been an error.
   void NotifyError(llvm::StringRef error);
 
+#if defined(_WIN32)
+  /// Connect to RunInTerminalDebugAdapterCommChannel instance.
+  bool Connect();
+#endif
+
 private:
   FifoFileIO m_io;
 };
 
 class RunInTerminalDebugAdapterCommChannel {
 public:
-  RunInTerminalDebugAdapterCommChannel(llvm::StringRef comm_file);
+  RunInTerminalDebugAdapterCommChannel(std::shared_ptr<FifoFile> comm_file);
 
   /// Notify the runInTerminal launcher that it was attached.
   ///
@@ -118,6 +126,11 @@ class RunInTerminalDebugAdapterCommChannel {
   /// default error message if a certain timeout if reached.
   std::string GetLauncherError();
 
+#if defined(_WIN32)
+  /// Connect to RunInTerminalLauncherCommChannel instance.
+  bool Connect();
+#endif
+
 private:
   FifoFileIO m_io;
 };
@@ -126,6 +139,14 @@ class RunInTerminalDebugAdapterCommChannel {
 /// the runInTerminal launcher.
 llvm::Expected<std::shared_ptr<FifoFile>> CreateRunInTerminalCommFile();
 
+/// Open a fifo file used to communicate the debug adaptor with
+/// the runInTerminal launcher.
+///
+/// \param[in] fifo_file
+///    The path to a fifo file that exists in the file system.
+llvm::Expected<std::shared_ptr<FifoFile>>
+OpenRunInTerminalCommFile(llvm::StringRef fifo_file);
+
 } // namespace lldb_dap
 
 #endif // LLDB_TOOLS_LLDB_DAP_RUNINTERMINAL_H
diff --git a/lldb/tools/lldb-dap/lldb-dap.cpp b/lldb/tools/lldb-dap/lldb-dap.cpp
index 6e17b13cc9e33..13fdd0e57ad1a 100644
--- a/lldb/tools/lldb-dap/lldb-dap.cpp
+++ b/lldb/tools/lldb-dap/lldb-dap.cpp
@@ -44,9 +44,11 @@
 #include <cstdio>
 #include <cstdlib>
 #include <fcntl.h>
+#include <iomanip>
 #include <map>
 #include <memory>
 #include <mutex>
+#include <sstream>
 #include <string>
 #include <system_error>
 #include <thread>
@@ -204,14 +206,73 @@ static void PrintVersion() {
 // In case of errors launching the target, a suitable error message will be
 // emitted to the debug adapter.
 static llvm::Error LaunchRunInTerminalTarget(llvm::opt::Arg &target_arg,
-                                             llvm::StringRef comm_file,
+                                             llvm::StringRef fifo_file,
                                              lldb::pid_t debugger_pid,
                                              char *argv[]) {
+  llvm::Expected<std::shared_ptr<FifoFile>> comm_file_or_err =
+      OpenRunInTerminalCommFile(fifo_file);
+  if (!comm_file_or_err) {
+    llvm::errs() << llvm::toString(comm_file_or_err.takeError()) << "\n";
+    exit(EXIT_FAILURE);
+  }
+  std::shared_ptr<FifoFile> comm_file = *comm_file_or_err;
+  RunInTerminalLauncherCommChannel comm_channel(comm_file);
+
 #if defined(_WIN32)
-  return llvm::createStringError(
-      "runInTerminal is only supported on POSIX systems");
-#else
+  if (!comm_channel.Connect()) {
+    llvm::errs() << "Failed to connect to the named pipe.\n";
+    exit(EXIT_FAILURE);
+  }
+
+  STARTUPINFOA si;
+  PROCESS_INFORMATION pi;
+  ZeroMemory(&si, sizeof(si));
+  si.cb = sizeof(si);
+  ZeroMemory(&pi, sizeof(pi));
+
+  std::string cmd;
+  while (*argv != nullptr) {
+    std::stringstream ss;
+    ss << std::quoted(*(argv++));
+    cmd += ss.str();
+    cmd += " ";
+  }
+  cmd.pop_back();
+
+  if (!CreateProcessA(NULL, cmd.data(), NULL, NULL, FALSE, CREATE_SUSPENDED,
+                      NULL, NULL, &si, &pi)) {
+    llvm::errs() << "Create process failed: " << GetLastError() << "\n";
+    exit(EXIT_FAILURE);
+  }
 
+  if (llvm::Error err = comm_channel.NotifyPid(pi.dwProcessId)) {
+    llvm::errs() << llvm::toString(std::move(err)) << "\n";
+    exit(EXIT_FAILURE);
+  }
+
+  // We will wait to be attached with a timeout. We don't wait indefinitely
+  // using a signal to prevent being paused forever.
+
+  // This env var should be used only for tests.
+  const char *timeout_env_var = getenv("LLDB_DAP_RIT_TIMEOUT_IN_MS");
+  int timeout_in_ms =
+      timeout_env_var != nullptr ? atoi(timeout_env_var) : 20000;
+  if (llvm::Error err = comm_channel.WaitUntilDebugAdapterAttaches(
+          std::chrono::milliseconds(timeout_in_ms))) {
+    llvm::errs() << llvm::toString(std::move(err)) << "\n";
+    exit(EXIT_FAILURE);
+  }
+
+  if (ResumeThread(pi.hThread) == (DWORD)-1) {
+    llvm::errs() << "Resume process failed: " << GetLastError() << "\n";
+    exit(EXIT_FAILURE);
+  }
+
+  WaitForSingleObject(pi.hProcess, INFINITE);
+  CloseHandle(pi.hProcess);
+  CloseHandle(pi.hThread);
+  exit(EXIT_SUCCESS);
+#else
   // On Linux with the Yama security module enabled, a process can only attach
   // to its descendants by default. In the runInTerminal case the target
   // process is launched by the client so we need to allow tracing explicitly.
@@ -220,8 +281,7 @@ static llvm::Error LaunchRunInTerminalTarget(llvm::opt::Arg 
&target_arg,
     (void)prctl(PR_SET_PTRACER, debugger_pid, 0, 0, 0);
 #endif
 
-  RunInTerminalLauncherCommChannel comm_channel(comm_file);
-  if (llvm::Error err = comm_channel.NotifyPid())
+  if (llvm::Error err = comm_channel.NotifyPid(getpid()))
     return err;
 
   // We will wait to be attached with a timeout. We don't wait indefinitely

_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to