Author: Charles Zablit
Date: 2026-06-17T14:24:07+01:00
New Revision: f87ac0815c08866bc9ec60fc31fe082cdb21bab0

URL: 
https://github.com/llvm/llvm-project/commit/f87ac0815c08866bc9ec60fc31fe082cdb21bab0
DIFF: 
https://github.com/llvm/llvm-project/commit/f87ac0815c08866bc9ec60fc31fe082cdb21bab0.diff

LOG: [lldb][Windows] use pipes when no terminal dimensions are sent (#203562)

Plumb `eLaunchFlagUsePipes` from the lldb-dap client through the
gdb-remote protocol to lldb-server so the server's LaunchProcess can
choose between ConPTY and anonymous pipes for inferior stdio.

This is needed for LLDB DAP in `internalConsole` mode.

Fixes `TestDAP_launch_args.py`, `TestDAP_launch_basic.py`, and
`TestDAP_launch_shellExpandArguments_disabled.py` on Windows under
`LLDB_USE_LLDB_SERVER=1`.

rdar://178725958

Added: 
    

Modified: 
    lldb/docs/resources/lldbgdbremote.md
    lldb/include/lldb/Host/ProcessLaunchInfo.h
    lldb/source/Host/windows/PseudoConsole.cpp
    
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
    lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
    lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/docs/resources/lldbgdbremote.md 
b/lldb/docs/resources/lldbgdbremote.md
index 10e0daf37448e..577a5ad31674f 100644
--- a/lldb/docs/resources/lldbgdbremote.md
+++ b/lldb/docs/resources/lldbgdbremote.md
@@ -1145,12 +1145,15 @@ this packet specifies the initial terminal dimensions:
 ```
 QSetSTDIOWindowSize:cols=<N>;rows=<N>
 ```
-Both `cols` and `rows` must be non-zero unsigned 16-bit integers. If sent,
-this packet must be sent _prior_ to the launch args (`A`) packet; sending it
-after the inferior has been launched has no effect. On the server side, the
-dimensions are stored and later applied to the PTY when the inferior is
-launched, via `TIOCSWINSZ` (POSIX) or the equivalent platform mechanism (e.g.
-`ConPTY` resize on Windows).
+Both `cols` and `rows` must be unsigned 16-bit integers. They must either both
+be non-zero, or both be zero. Any other combination (e.g. `cols=80;rows=0`) is
+treated as a malformed packet. This packet must be sent _prior_ to the launch
+args (`A`) packet; sending it after the inferior has been launched has no
+effect.
+
+On the server side, the dimensions are stored and applied to the PTY at launch
+time. On POSIX this is done via `TIOCSWINSZ`; on Windows via `ConPTY` resize.
+If both dimensions are zero, the server uses pipes instead of a PTY on all 
platforms.
 
 The response is either:
 * `OK`: dimensions accepted; they will be applied to the PTY when the

diff  --git a/lldb/include/lldb/Host/ProcessLaunchInfo.h 
b/lldb/include/lldb/Host/ProcessLaunchInfo.h
index 99f4d48aa4f27..096d51357d857 100644
--- a/lldb/include/lldb/Host/ProcessLaunchInfo.h
+++ b/lldb/include/lldb/Host/ProcessLaunchInfo.h
@@ -184,8 +184,15 @@ class ProcessLaunchInfo : public ProcessInfo {
   void SetSTDIOWindowSize(uint16_t cols, uint16_t rows) {
     m_stdio_window_size.cols = cols;
     m_stdio_window_size.rows = rows;
+    m_stdio_window_size_explicit = true;
   }
 
+  bool IsSTDIOWindowSizeExplicit() const {
+    return m_stdio_window_size_explicit;
+  }
+
+  STDIOWindowSize GetSTDIOWindowSize() const { return m_stdio_window_size; }
+
 protected:
   FileSpec m_working_dir;
   std::string m_plugin_name;
@@ -199,6 +206,7 @@ class ProcessLaunchInfo : public ProcessInfo {
   std::string m_event_data; // A string passed to the plugin launch, having no
                             // meaning to the upper levels of lldb.
   STDIOWindowSize m_stdio_window_size;
+  bool m_stdio_window_size_explicit = false;
 };
 }
 

diff  --git a/lldb/source/Host/windows/PseudoConsole.cpp 
b/lldb/source/Host/windows/PseudoConsole.cpp
index 2b8293393bfdf..3a28adacfea53 100644
--- a/lldb/source/Host/windows/PseudoConsole.cpp
+++ b/lldb/source/Host/windows/PseudoConsole.cpp
@@ -188,6 +188,8 @@ void PseudoConsole::Close() {
   std::unique_lock<std::mutex> guard(m_mutex);
   if (m_conpty_handle != INVALID_HANDLE_VALUE)
     kernel32.ClosePseudoConsole(m_conpty_handle);
+  if (m_mode == Mode::Pipe && m_conpty_output != INVALID_HANDLE_VALUE)
+    CancelIoEx(m_conpty_output, nullptr);
   m_conpty_handle = INVALID_HANDLE_VALUE;
   SetStopping(false);
   m_cv.notify_all();

diff  --git 
a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp 
b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
index d676699ef3176..d710dfec95873 100644
--- 
a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
+++ 
b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
@@ -991,7 +991,10 @@ 
GDBRemoteCommunicationServerCommon::Handle_QSetSTDIOWindowSize(
       continue;
     *dest = static_cast<uint16_t>(parsed);
   }
-  if (cols == 0 || rows == 0)
+  // 0x0 is a valid request: it signals "no terminal" and a redirection
+  // backend that supports an alternative path (anonymous pipes on Windows
+  // ConPTY) can switch on it. Reject only the malformed cases.
+  if ((cols == 0) != (rows == 0))
     return SendErrorResponse(28);
 
   m_process_launch_info.SetSTDIOWindowSize(cols, rows);

diff  --git 
a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp 
b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index 0f14231cadbd5..f265fcb71be4e 100644
--- 
a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ 
b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -291,8 +291,21 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() {
   m_process_launch_info.GetFlags().Set(eLaunchFlagDebug);
 
   if (should_forward_stdio) {
+#if defined(_WIN32)
+    ProcessLaunchInfo::STDIOWindowSize win_size =
+        m_process_launch_info.GetSTDIOWindowSize();
+    if (m_process_launch_info.IsSTDIOWindowSizeExplicit() &&
+        win_size.cols == 0 && win_size.rows == 0) {
+      if (llvm::Error Err = m_process_launch_info.SetUpPipeRedirection())
+        return Status::FromError(std::move(Err));
+    } else {
+      if (llvm::Error Err = m_process_launch_info.SetUpPtyRedirection())
+        return Status::FromError(std::move(Err));
+    }
+#else
     if (llvm::Error Err = m_process_launch_info.SetUpPtyRedirection())
       return Status::FromError(std::move(Err));
+#endif
   }
 
   {

diff  --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp 
b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 2fc6dbb546f79..5f59cbeb2dda0 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -843,8 +843,12 @@ Status ProcessGDBRemote::DoLaunch(lldb_private::Module 
*exe_module,
     if (stderr_file_spec)
       m_gdb_comm.SetSTDERR(stderr_file_spec);
 
-    auto [terminal_cols, terminal_rows] = GetClientTerminalSize();
-    m_gdb_comm.SetSTDIOWindowSize(terminal_cols, terminal_rows);
+    if (launch_flags & eLaunchFlagUsePipes) {
+      m_gdb_comm.SetSTDIOWindowSize(0, 0);
+    } else {
+      auto [terminal_cols, terminal_rows] = GetClientTerminalSize();
+      m_gdb_comm.SetSTDIOWindowSize(terminal_cols, terminal_rows);
+    }
 
     m_gdb_comm.SetDisableASLR(launch_flags & eLaunchFlagDisableASLR);
     m_gdb_comm.SetDetachOnError(launch_flags & eLaunchFlagDetachOnError);


        
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to