[Lldb-commits] [lldb] [lldb-dap][windows] add integratedTerminal support (PR #174635)

Sergei Druzhkov via lldb-commits lldb-commits at lists.llvm.org
Tue Feb 3 11:57:56 PST 2026


================
@@ -285,6 +304,111 @@ static llvm::Error LaunchRunInTerminalTarget(llvm::opt::Arg &target_arg,
 #endif
 
   lldb_private::FileSystem::Initialize();
+
+#ifdef _WIN32
+  RunInTerminalLauncherCommChannel comm_channel(comm_file);
+
+  auto wcommandLineOrErr =
+      lldb_private::GetFlattenedWindowsCommandStringW(argv);
+  if (!wcommandLineOrErr)
+    return notifyError(comm_channel, "Failed to process arguments");
+
+  STARTUPINFOEXW startupinfoex = {};
+  startupinfoex.StartupInfo.cb = sizeof(STARTUPINFOEXW);
+  startupinfoex.StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
+
+  HANDLE stdin_handle = GetStdHandle(STD_INPUT_HANDLE);
+  HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
+  HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
+
+  auto attributelist_or_err =
+      lldb_private::ProcThreadAttributeList::Create(startupinfoex);
+  if (!attributelist_or_err) {
+    return notifyError(comm_channel, "Could not open inherited handles",
+                       attributelist_or_err.getError());
+  }
+
+  if (!stdio.empty()) {
+    llvm::SmallVector<llvm::StringRef, 3> files;
+    stdio.split(files, ';');
+    while (files.size() < 3)
+      files.push_back(files.back());
+
+    stdin_handle = lldb_private::ProcessLauncherWindows::GetStdioHandle(
+        files[0], STDIN_FILENO);
+    stdout_handle = lldb_private::ProcessLauncherWindows::GetStdioHandle(
+        files[1], STDOUT_FILENO);
+    stderr_handle = lldb_private::ProcessLauncherWindows::GetStdioHandle(
+        files[2], STDERR_FILENO);
+  }
+
+  llvm::scope_exit close_handles([&] {
+    // Only close the handles we created
+    if (stdio.empty())
+      return;
+    if (stdin_handle)
+      CloseHandle(stdin_handle);
+    if (stdout_handle)
+      CloseHandle(stdout_handle);
+    if (stderr_handle)
+      CloseHandle(stderr_handle);
+  });
+
+  auto inherited_handles_or_err =
+      lldb_private::ProcessLauncherWindows::GetInheritedHandles(
+          startupinfoex, /*launch_info*=*/nullptr, stdout_handle, stderr_handle,
+          stdin_handle);
+
+  if (!inherited_handles_or_err)
+    return notifyError(comm_channel, "Failed to get inherited handles",
+                       inherited_handles_or_err.getError());
+  std::vector<HANDLE> inherited_handles = std::move(*inherited_handles_or_err);
+
+  PROCESS_INFORMATION pi = {};
+
+  // Start the process in a suspended state, while we attach the debugger.
+  BOOL result = CreateProcessW(
+      /*lpApplicationName=*/NULL, /*lpCommandLine=*/&(*wcommandLineOrErr)[0],
+      /*lpProcessAttributes=*/NULL, /*lpThreadAttributes=*/NULL,
+      /*bInheritHandles=*/!inherited_handles.empty(),
+      /*dwCreationFlags=*/CREATE_SUSPENDED, /*lpEnvironment=*/NULL,
+      /*lpCurrentDirectory=*/NULL,
+      /*lpStartupInfo=*/reinterpret_cast<STARTUPINFOW *>(&startupinfoex),
+      /*lpProcessInformation=*/&pi);
+
+  if (!result)
+    return notifyError(comm_channel, "Failed to launch target process");
+
+  auto cleanupAndReturn = [&](llvm::Error err) -> llvm::Error {
+    if (pi.hProcess)
+      TerminateProcess(pi.hProcess, 1);
+    if (pi.hThread)
+      CloseHandle(pi.hThread);
+    if (pi.hProcess)
+      CloseHandle(pi.hProcess);
+    return err;
+  };
+
+  // Notify the pid of the process to debug to the debugger. It will attach to
+  // the newly created process.
+  if (llvm::Error err = comm_channel.NotifyPid(pi.dwProcessId))
+    return cleanupAndReturn(std::move(err));
+
+  if (llvm::Error err = comm_channel.WaitUntilDebugAdapterAttaches(
+          std::chrono::milliseconds(timeout_in_ms)))
+    return cleanupAndReturn(std::move(err));
+
+  // The debugger attached to the process. We can resume it.
+  if (!ResumeThread(pi.hThread))
+    return cleanupAndReturn(
+        notifyError(comm_channel, "Failed to resume the target process"));
+
+  // Wait for child to complete to match POSIX behavior.
+  WaitForSingleObject(pi.hProcess, INFINITE);
+  CloseHandle(pi.hThread);
+  CloseHandle(pi.hProcess);
+  return llvm::Error::success();
----------------
DrSergei wrote:

I guess we should insert `exit(0)` to match POSIX behavior when exec never returns. Without that we trigger assert in `SBDebugger` initialization.

```
PS D:\projects\pipes>  & 'D:\llvm-project\build-nopython-debug\bin\lldb-dap.exe' '--comm-file' '\\.\pipe\lldb-dap-run-in-terminal-comm-3900' '--stdio' ';tmp.txt;tmp.txt' '--launch-target' 'D:\projects\pipes/main.exe' 
Assertion failed: !InstanceImpl() && "Already initialized.", file D:\llvm-project\lldb\include\lldb/Host/FileSystem.h, line 51
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.      Program arguments: D:\\llvm-project\\build-nopython-debug\\bin\\lldb-dap.exe --comm-file \\\\.\\pipe\\lldb-dap-run-in-terminal-comm-3900 --stdio ;tmp.txt;tmp.txt --launch-target D:\\projects\\pipes/main.exe
Exception Code: 0x80000003
 #0 0x00007ff6bf759ebc HandleAbort D:\llvm-project\llvm\lib\Support\Windows\Signals.inc:371:0
 #1 0x00007ffc111990ed (C:\WINDOWS\SYSTEM32\ucrtbased.dll+0xa90ed)
 #2 0x00007ffc1119ae49 (C:\WINDOWS\SYSTEM32\ucrtbased.dll+0xaae49)
 #3 0x00007ffc111a1345 (C:\WINDOWS\SYSTEM32\ucrtbased.dll+0xb1345)
 #4 0x00007ffc111a0bd7 (C:\WINDOWS\SYSTEM32\ucrtbased.dll+0xb0bd7)
 #5 0x00007ffc1119eba1 (C:\WINDOWS\SYSTEM32\ucrtbased.dll+0xaeba1)
 #6 0x00007ffc111a18af (C:\WINDOWS\SYSTEM32\ucrtbased.dll+0xb18af)
 #7 0x00007ffb3352a8f0 lldb_private::FileSystem::Initialize<>(void) D:\llvm-project\lldb\include\lldb\Host\FileSystem.h:51:0
 #8 0x00007ffb3352a407 lldb_private::SystemInitializerCommon::Initialize(void) D:\llvm-project\lldb\source\Initialization\SystemInitializerCommon.cpp:71:0    
 #9 0x00007ffb331b6d5e lldb_private::SystemInitializerFull::Initialize(void) D:\llvm-project\lldb\source\API\SystemInitializerFull.cpp:54:0
#10 0x00007ffb33529c9b lldb_private::SystemLifetimeManager::Initialize(class std::unique_ptr<class lldb_private::SystemInitializer, struct std::default_delete<class lldb_private::SystemInitializer>>) D:\llvm-project\lldb\source\Initialization\SystemLifetimeManager.cpp:34:0
#11 0x00007ffb32fbda99 lldb::SBDebugger::InitializeWithErrorHandling(void) D:\llvm-project\lldb\source\API\SBDebugger.cpp:183:0
#12 0x00007ff6bf62ea13 main D:\llvm-project\lldb\tools\lldb-dap\tool\lldb-dap.cpp:775:0
#13 0x00007ff6bfa8ac49 invoke_main D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:79:0
#14 0x00007ff6bfa8ab32 __scrt_common_main_seh D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288:0
#15 0x00007ff6bfa8a9ee __scrt_common_main D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:331:0
#16 0x00007ff6bfa8acde mainCRTStartup D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp:17:0
#17 0x00007ffc4fd5e8d7 (C:\WINDOWS\System32\KERNEL32.DLL+0x2e8d7)
#18 0x00007ffc5128c53c (C:\WINDOWS\SYSTEM32\ntdll.dll+0x8c53c)
```

https://github.com/llvm/llvm-project/pull/174635


More information about the lldb-commits mailing list