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
