Skip to content

Conversation

@charles-zablit
Copy link
Contributor

@charles-zablit charles-zablit commented Nov 19, 2025

@llvmbot
Copy link
Member

llvmbot commented Nov 19, 2025

@llvm/pr-subscribers-lldb

Author: Charles Zablit (charles-zablit)

Changes

Patch is 59.24 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/168729.diff

33 Files Affected:

  • (modified) lldb/include/lldb/Host/ProcessLaunchInfo.h (+1-1)
  • (modified) lldb/include/lldb/Host/PseudoTerminal.h (+31-9)
  • (added) lldb/include/lldb/Host/windows/ConnectionPseudoTerminalWindows.h (+61)
  • (modified) lldb/include/lldb/Host/windows/ProcessLauncherWindows.h (+29)
  • (added) lldb/include/lldb/Host/windows/PseudoTerminalWindows.h (+37)
  • (modified) lldb/include/lldb/Host/windows/windows.h (+3-2)
  • (modified) lldb/include/lldb/Target/Process.h (+30)
  • (modified) lldb/source/Host/CMakeLists.txt (+2)
  • (modified) lldb/source/Host/common/ProcessLaunchInfo.cpp (+16-3)
  • (modified) lldb/source/Host/common/PseudoTerminal.cpp (+4-8)
  • (added) lldb/source/Host/windows/ConnectionPseudoTerminalWindows.cpp (+191)
  • (modified) lldb/source/Host/windows/ProcessLauncherWindows.cpp (+91-73)
  • (added) lldb/source/Host/windows/PseudoTerminalWindows.cpp (+68)
  • (modified) lldb/source/Interpreter/ScriptInterpreter.cpp (+1-1)
  • (modified) lldb/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp (+1-1)
  • (modified) lldb/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.mm (+5-5)
  • (modified) lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp (+1-1)
  • (modified) lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.cpp (+2-2)
  • (modified) lldb/source/Plugins/Platform/Windows/PlatformWindows.cpp (+10-2)
  • (modified) lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp (+3-2)
  • (modified) lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp (+2-2)
  • (modified) lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp (+2-2)
  • (modified) lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp (+2-2)
  • (modified) lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp (+3-3)
  • (modified) lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp (+17-16)
  • (modified) lldb/source/Plugins/Process/Windows/Common/ProcessWindows.h (+4-4)
  • (modified) lldb/source/Target/Platform.cpp (+1-1)
  • (modified) lldb/source/Target/Process.cpp (+9-8)
  • (modified) lldb/test/API/commands/platform/basic/TestPlatformCommand.py (+1)
  • (modified) lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py (-1)
  • (modified) lldb/tools/lldb-dap/tool/lldb-dap.cpp (+3)
  • (modified) lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp (+19-15)
  • (modified) llvm/utils/gn/secondary/lldb/source/Host/BUILD.gn (+2)
diff --git a/lldb/include/lldb/Host/ProcessLaunchInfo.h b/lldb/include/lldb/Host/ProcessLaunchInfo.h
index 25762bc65295d..50a5af604ee26 100644
--- a/lldb/include/lldb/Host/ProcessLaunchInfo.h
+++ b/lldb/include/lldb/Host/ProcessLaunchInfo.h
@@ -118,7 +118,7 @@ class ProcessLaunchInfo : public ProcessInfo {
 
   bool MonitorProcess() const;
 
-  PseudoTerminal &GetPTY() { return *m_pty; }
+  std::shared_ptr<PseudoTerminal> GetPTY() const { return m_pty; }
 
   void SetLaunchEventData(const char *data) { m_event_data.assign(data); }
 
diff --git a/lldb/include/lldb/Host/PseudoTerminal.h b/lldb/include/lldb/Host/PseudoTerminal.h
index bd1e2f56241b2..b61c213e138cb 100644
--- a/lldb/include/lldb/Host/PseudoTerminal.h
+++ b/lldb/include/lldb/Host/PseudoTerminal.h
@@ -35,11 +35,14 @@ class PseudoTerminal {
 
   /// Destructor
   ///
-  /// The destructor will close the primary and secondary file descriptors if
-  /// they are valid and ownership has not been released using one of: @li
-  /// PseudoTerminal::ReleasePrimaryFileDescriptor() @li
-  /// PseudoTerminal::ReleaseSaveFileDescriptor()
-  ~PseudoTerminal();
+  /// The destructor will close the primary and secondary file
+  /// descriptor/HANDLEs if they are valid and ownership has not been released
+  /// using PseudoTerminal::Close().
+  virtual ~PseudoTerminal();
+
+  /// Close all the file descriptors or Handles of the PseudoTerminal if they
+  /// are valid.
+  virtual void Close();
 
   /// Close the primary file descriptor if it is valid.
   void ClosePrimaryFileDescriptor();
@@ -59,8 +62,7 @@ class PseudoTerminal {
   ///
   /// This class will close the file descriptors for the primary/secondary when
   /// the destructor is called. The file handles can be released using either:
-  /// @li PseudoTerminal::ReleasePrimaryFileDescriptor() @li
-  /// PseudoTerminal::ReleaseSaveFileDescriptor()
+  /// @li PseudoTerminal::ReleasePrimaryFileDescriptor()
   ///
   /// \return
   ///     \b Parent process: a child process ID that is greater
@@ -82,6 +84,16 @@ class PseudoTerminal {
   /// \see PseudoTerminal::ReleasePrimaryFileDescriptor()
   int GetPrimaryFileDescriptor() const;
 
+  /// The primary HANDLE accessor.
+  ///
+  /// This object retains ownership of the primary HANDLE when this
+  /// accessor is used.
+  ///
+  /// \return
+  ///     The primary HANDLE, or INVALID_HANDLE_VALUE if the primary HANDLE is
+  ///     not currently valid.
+  virtual void *GetPrimaryHandle() const { return ((void *)(long long)-1); };
+
   /// The secondary file descriptor accessor.
   ///
   /// This object retains ownership of the secondary file descriptor when this
@@ -105,7 +117,17 @@ class PseudoTerminal {
   ///     The name of the secondary pseudo terminal.
   ///
   /// \see PseudoTerminal::OpenFirstAvailablePrimary()
-  std::string GetSecondaryName() const;
+  virtual std::string GetSecondaryName() const;
+
+  /// The underlying Windows Pseudo Terminal HANDLE's accessor.
+  ///
+  /// This object retains ownership of the ConPTY's HANDLE when this
+  /// accessor is used.
+  ///
+  /// \return
+  ///     The primary HANDLE, or INVALID_HANDLE_VALUE if the primary HANDLE is
+  ///     not currently valid.
+  virtual void *GetPseudoTerminalHandle() { return ((void *)(long long)-1); };
 
   /// Open the first available pseudo terminal.
   ///
@@ -126,7 +148,7 @@ class PseudoTerminal {
   ///
   /// \see PseudoTerminal::GetPrimaryFileDescriptor() @see
   /// PseudoTerminal::ReleasePrimaryFileDescriptor()
-  llvm::Error OpenFirstAvailablePrimary(int oflag);
+  virtual llvm::Error OpenFirstAvailablePrimary(int oflag);
 
   /// Open the secondary for the current primary pseudo terminal.
   ///
diff --git a/lldb/include/lldb/Host/windows/ConnectionPseudoTerminalWindows.h b/lldb/include/lldb/Host/windows/ConnectionPseudoTerminalWindows.h
new file mode 100644
index 0000000000000..6283312db7b8d
--- /dev/null
+++ b/lldb/include/lldb/Host/windows/ConnectionPseudoTerminalWindows.h
@@ -0,0 +1,61 @@
+//===-- ConnectionPseudoTerminalWindows.h ------------------------*- C++
+//-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_Host_windows_ConnectionPseudoConsoleWindows_h_
+#define liblldb_Host_windows_ConnectionPseudoConsoleWindows_h_
+
+#include "lldb/Host/windows/PseudoTerminalWindows.h"
+#include "lldb/Host/windows/windows.h"
+#include "lldb/Utility/Connection.h"
+#include "lldb/Utility/Status.h"
+#include "lldb/lldb-types.h"
+
+namespace lldb_private {
+
+class ConnectionPseudoTerminal : public lldb_private::Connection {
+public:
+  ConnectionPseudoTerminal();
+
+  ConnectionPseudoTerminal(std::shared_ptr<PseudoTerminal> pty, bool owns_file);
+
+  ~ConnectionPseudoTerminal() override;
+
+  bool IsConnected() const override;
+
+  lldb::ConnectionStatus Connect(llvm::StringRef url,
+                                 Status *error_ptr) override;
+
+  lldb::ConnectionStatus Disconnect(Status *error_ptr) override;
+
+  size_t Read(void *dst, size_t dst_len, const Timeout<std::micro> &timeout,
+              lldb::ConnectionStatus &status, Status *error_ptr) override;
+
+  size_t Write(const void *src, size_t src_len, lldb::ConnectionStatus &status,
+               Status *error_ptr) override;
+
+  std::string GetURI() override { return ""; };
+
+  bool InterruptRead() override;
+
+protected:
+  std::shared_ptr<PseudoTerminal> m_pty;
+  OVERLAPPED m_overlapped;
+  bool m_owns_file;
+  HANDLE m_event_handles[2];
+
+  enum { kBytesAvailableEvent, kInterruptEvent };
+
+private:
+  ConnectionPseudoTerminal(const ConnectionPseudoTerminal &) = delete;
+  const ConnectionPseudoTerminal &
+  operator=(const ConnectionPseudoTerminal &) = delete;
+};
+} // namespace lldb_private
+
+#endif
diff --git a/lldb/include/lldb/Host/windows/ProcessLauncherWindows.h b/lldb/include/lldb/Host/windows/ProcessLauncherWindows.h
index 81aea5b2022a5..a04077a5e1d03 100644
--- a/lldb/include/lldb/Host/windows/ProcessLauncherWindows.h
+++ b/lldb/include/lldb/Host/windows/ProcessLauncherWindows.h
@@ -11,6 +11,9 @@
 
 #include "lldb/Host/ProcessLauncher.h"
 #include "lldb/Host/windows/windows.h"
+#include "lldb/Utility/Args.h"
+#include "lldb/Utility/Environment.h"
+#include "llvm/Support/ErrorOr.h"
 
 namespace lldb_private {
 
@@ -23,6 +26,32 @@ class ProcessLauncherWindows : public ProcessLauncher {
 
 protected:
   HANDLE GetStdioHandle(const ProcessLaunchInfo &launch_info, int fd);
+
+  /// Create a UTF-16 environment block to use with CreateProcessW.
+  ///
+  /// The buffer is a sequence of null-terminated UTF-16 strings, followed by an
+  /// extra L'\0' (two bytes of 0). An empty environment must have one
+  /// empty string, followed by an extra L'\0'.
+  ///
+  /// The keys are sorted to comply with the CreateProcess' calling convention.
+  ///
+  /// Ensure that the resulting buffer is used in conjunction with
+  /// CreateProcessW and be sure that dwCreationFlags includes
+  /// CREATE_UNICODE_ENVIRONMENT.
+  ///
+  /// \param env The Environment object to convert.
+  /// \returns The sorted sequence of environment variables and their values,
+  /// separated by null terminators.
+  static std::vector<wchar_t> CreateEnvironmentBufferW(const Environment &env);
+
+  /// Flattens an Args object into a Windows command-line wide string.
+  ///
+  /// Returns an empty string if args is empty.
+  ///
+  /// \param args The Args object to flatten.
+  /// \returns A wide string containing the flattened command line.
+  static llvm::ErrorOr<std::wstring>
+  GetFlattenedWindowsCommandStringW(Args args);
 };
 }
 
diff --git a/lldb/include/lldb/Host/windows/PseudoTerminalWindows.h b/lldb/include/lldb/Host/windows/PseudoTerminalWindows.h
new file mode 100644
index 0000000000000..8698ae2f8b804
--- /dev/null
+++ b/lldb/include/lldb/Host/windows/PseudoTerminalWindows.h
@@ -0,0 +1,37 @@
+//===-- PseudoTerminalWindows.h ---------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_Host_Windows_PseudoTerminalWindows_H_
+#define liblldb_Host_Windows_PseudoTerminalWindows_H_
+
+#include "lldb/Host/PseudoTerminal.h"
+#include "lldb/Host/windows/windows.h"
+
+namespace lldb_private {
+
+class PseudoTerminalWindows : public PseudoTerminal {
+
+public:
+  void Close() override;
+
+  HPCON GetPseudoTerminalHandle() override { return m_conpty_handle; };
+
+  HANDLE GetPrimaryHandle() const override { return m_conpty_output; };
+
+  std::string GetSecondaryName() const override { return ""; };
+
+  llvm::Error OpenFirstAvailablePrimary(int oflag) override;
+
+protected:
+  HANDLE m_conpty_handle = INVALID_HANDLE_VALUE;
+  HANDLE m_conpty_output = INVALID_HANDLE_VALUE;
+  HANDLE m_conpty_input = INVALID_HANDLE_VALUE;
+};
+}; // namespace lldb_private
+
+#endif // liblldb_Host_Windows_PseudoTerminalWindows_H_
\ No newline at end of file
diff --git a/lldb/include/lldb/Host/windows/windows.h b/lldb/include/lldb/Host/windows/windows.h
index d53d4b9967268..2047e602291fc 100644
--- a/lldb/include/lldb/Host/windows/windows.h
+++ b/lldb/include/lldb/Host/windows/windows.h
@@ -9,9 +9,9 @@
 #ifndef LLDB_lldb_windows_h_
 #define LLDB_lldb_windows_h_
 
-#define NTDDI_VERSION NTDDI_VISTA
+// #define NTDDI_VERSION NTDDI_VISTA
 #undef _WIN32_WINNT // undef a previous definition to avoid warning
-#define _WIN32_WINNT _WIN32_WINNT_VISTA
+// #define _WIN32_WINNT _WIN32_WINNT_VISTA
 #define WIN32_LEAN_AND_MEAN
 #define NOGDI
 #undef NOMINMAX // undef a previous definition to avoid warning
@@ -26,6 +26,7 @@
 #undef near
 #undef FAR
 #undef NEAR
+#undef WIN32_MEMORY_INFORMATION_CLASS
 #define FAR
 #define NEAR
 
diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index c1f9785e76f90..17a8ce713302a 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -2534,8 +2534,38 @@ void PruneThreadPlans();
 
   void CalculateExecutionContext(ExecutionContext &exe_ctx) override;
 
+  /// Associates a file descriptor with the process's STDIO handling
+  /// and configures an asynchronous reading of that descriptor.
+  ///
+  /// This method installs a ConnectionFileDescriptor for the passed file
+  /// descriptor and starts a dedicated read thread. If the read thread starts
+  /// successfully, the method also ensures that an IOHandlerProcessSTDIO is
+  /// created to manage user input to the process.
+  ///
+  /// The descriptor's ownership is transferred to the underlying
+  /// ConnectionFileDescriptor.
+  ///
+  /// \param[in] fd
+  ///     The file descriptor to use for process STDIO communication. It's
+  ///     assumed to be valid and will be managed by the newly created
+  ///     connection.
+  ///
+  /// \see lldb_private::Process::STDIOReadThreadBytesReceived()
+  /// \see lldb_private::IOHandlerProcessSTDIO
+  /// \see lldb_private::ConnectionFileDescriptor
   void SetSTDIOFileDescriptor(int file_descriptor);
 
+  /// Windows equivalent of Process::SetSTDIOFileDescriptor, with a
+  /// PseudoTerminalWindows instead of a file descriptor.
+  ///
+  /// \param pty
+  ///     The PseudoTerminal to use for process STDIO communication. It is not
+  ///     managed by the created read thread.
+  ///
+  /// \see lldb_private::ConnectionPseudoTerminalWindows
+  virtual void
+  SetPseudoTerminalHandle(const std::shared_ptr<PseudoTerminal> &pty) {};
+
   // Add a permanent region of memory that should never be read or written to.
   // This can be used to ensure that memory reads or writes to certain areas of
   // memory never end up being sent to the DoReadMemory or DoWriteMemory
diff --git a/lldb/source/Host/CMakeLists.txt b/lldb/source/Host/CMakeLists.txt
index c9e8afe48fcde..1657dadf5ffe7 100644
--- a/lldb/source/Host/CMakeLists.txt
+++ b/lldb/source/Host/CMakeLists.txt
@@ -66,6 +66,7 @@ add_host_subdirectory(posix
 if (CMAKE_SYSTEM_NAME MATCHES "Windows")
   add_host_subdirectory(windows
     windows/ConnectionGenericFileWindows.cpp
+    windows/ConnectionPseudoTerminalWindows.cpp
     windows/FileSystem.cpp
     windows/Host.cpp
     windows/HostInfoWindows.cpp
@@ -75,6 +76,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Windows")
     windows/MainLoopWindows.cpp
     windows/PipeWindows.cpp
     windows/ProcessLauncherWindows.cpp
+    windows/PseudoTerminalWindows.cpp
     windows/ProcessRunLock.cpp
     )
 else()
diff --git a/lldb/source/Host/common/ProcessLaunchInfo.cpp b/lldb/source/Host/common/ProcessLaunchInfo.cpp
index 49159cca9c57c..c3beef7031f18 100644
--- a/lldb/source/Host/common/ProcessLaunchInfo.cpp
+++ b/lldb/source/Host/common/ProcessLaunchInfo.cpp
@@ -20,7 +20,9 @@
 #include "llvm/Support/ConvertUTF.h"
 #include "llvm/Support/FileSystem.h"
 
-#if !defined(_WIN32)
+#ifdef _WIN32
+#include "lldb/Host/windows/PseudoTerminalWindows.h"
+#else
 #include <climits>
 #endif
 
@@ -31,7 +33,12 @@ using namespace lldb_private;
 
 ProcessLaunchInfo::ProcessLaunchInfo()
     : ProcessInfo(), m_working_dir(), m_plugin_name(), m_flags(0),
-      m_file_actions(), m_pty(new PseudoTerminal), m_monitor_callback(nullptr) {
+      m_file_actions(), m_monitor_callback(nullptr) {
+#ifdef _WIN32
+  m_pty = std::make_shared<PseudoTerminalWindows>();
+#else
+  m_pty = std::make_shared<PseudoTerminal>();
+#endif
 }
 
 ProcessLaunchInfo::ProcessLaunchInfo(const FileSpec &stdin_file_spec,
@@ -40,7 +47,13 @@ ProcessLaunchInfo::ProcessLaunchInfo(const FileSpec &stdin_file_spec,
                                      const FileSpec &working_directory,
                                      uint32_t launch_flags)
     : ProcessInfo(), m_working_dir(), m_plugin_name(), m_flags(launch_flags),
-      m_file_actions(), m_pty(new PseudoTerminal) {
+      m_file_actions() {
+#ifdef _WIN32
+  m_pty = std::make_shared<PseudoTerminalWindows>();
+#else
+  m_pty = std::make_shared<PseudoTerminal>();
+#endif
+
   if (stdin_file_spec) {
     FileAction file_action;
     const bool read = true;
diff --git a/lldb/source/Host/common/PseudoTerminal.cpp b/lldb/source/Host/common/PseudoTerminal.cpp
index 53e91aff212a4..4d062c3618523 100644
--- a/lldb/source/Host/common/PseudoTerminal.cpp
+++ b/lldb/source/Host/common/PseudoTerminal.cpp
@@ -9,6 +9,7 @@
 #include "lldb/Host/PseudoTerminal.h"
 #include "lldb/Host/Config.h"
 #include "lldb/Host/FileSystem.h"
+#include "lldb/Host/windows/windows.h"
 #include "llvm/Support/Errc.h"
 #include "llvm/Support/Errno.h"
 #include <cassert>
@@ -29,16 +30,11 @@
 
 using namespace lldb_private;
 
-// PseudoTerminal constructor
 PseudoTerminal::PseudoTerminal() = default;
 
-// Destructor
-//
-// The destructor will close the primary and secondary file descriptors if they
-// are valid and ownership has not been released using the
-// ReleasePrimaryFileDescriptor() or the ReleaseSaveFileDescriptor() member
-// functions.
-PseudoTerminal::~PseudoTerminal() {
+PseudoTerminal::~PseudoTerminal() { Close(); }
+
+void PseudoTerminal::Close() {
   ClosePrimaryFileDescriptor();
   CloseSecondaryFileDescriptor();
 }
diff --git a/lldb/source/Host/windows/ConnectionPseudoTerminalWindows.cpp b/lldb/source/Host/windows/ConnectionPseudoTerminalWindows.cpp
new file mode 100644
index 0000000000000..b00fd745bc409
--- /dev/null
+++ b/lldb/source/Host/windows/ConnectionPseudoTerminalWindows.cpp
@@ -0,0 +1,191 @@
+//===-- ConnectionPseudoConsoleWindowsWindows.cpp
+//----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Host/windows/ConnectionPseudoTerminalWindows.h"
+#include "lldb/Utility/LLDBLog.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/Status.h"
+#include "lldb/Utility/Timeout.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ConvertUTF.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+class ReturnInfo {
+public:
+  void Set(size_t bytes, ConnectionStatus status, DWORD error_code) {
+    m_error = Status(error_code, eErrorTypeWin32);
+    m_bytes = bytes;
+    m_status = status;
+  }
+
+  void Set(size_t bytes, ConnectionStatus status, llvm::StringRef error_msg) {
+    m_error = Status::FromErrorString(error_msg.data());
+    m_bytes = bytes;
+    m_status = status;
+  }
+
+  size_t GetBytes() const { return m_bytes; }
+  ConnectionStatus GetStatus() const { return m_status; }
+  const Status &GetError() const { return m_error; }
+
+private:
+  Status m_error;
+  size_t m_bytes;
+  ConnectionStatus m_status;
+};
+
+ConnectionPseudoTerminal::ConnectionPseudoTerminal()
+    : m_pty(nullptr), m_owns_file(false) {
+  ::ZeroMemory(&m_overlapped, sizeof(m_overlapped));
+}
+
+ConnectionPseudoTerminal::ConnectionPseudoTerminal(
+    std::shared_ptr<PseudoTerminal> pty, bool owns_file)
+    : m_pty(pty), m_owns_file(owns_file) {
+  ::ZeroMemory(&m_overlapped, sizeof(m_overlapped));
+}
+
+ConnectionPseudoTerminal::~ConnectionPseudoTerminal() {}
+
+lldb::ConnectionStatus ConnectionPseudoTerminal::Connect(llvm::StringRef url,
+                                                         Status *error_ptr) {
+  if (IsConnected())
+    return eConnectionStatusSuccess;
+  return eConnectionStatusNoConnection;
+}
+
+bool ConnectionPseudoTerminal::IsConnected() const {
+  return m_pty && (m_pty->GetPrimaryHandle() != INVALID_HANDLE_VALUE);
+}
+
+lldb::ConnectionStatus ConnectionPseudoTerminal::Disconnect(Status *error_ptr) {
+  Log *log = GetLog(LLDBLog::Connection);
+  LLDB_LOGF(log, "%p ConnectionPseudoTerminal::Disconnect ()",
+            static_cast<void *>(this));
+
+  if (!IsConnected())
+    return eConnectionStatusSuccess;
+
+  m_pty->Close();
+  return eConnectionStatusSuccess;
+}
+
+size_t ConnectionPseudoTerminal::Read(void *dst, size_t dst_len,
+                                      const Timeout<std::micro> &timeout,
+                                      lldb::ConnectionStatus &status,
+                                      Status *error_ptr) {
+  ReturnInfo return_info;
+  DWORD bytes_read = 0;
+  BOOL result = false;
+
+  if (error_ptr)
+    error_ptr->Clear();
+
+  HANDLE hInput = m_pty->GetPrimaryHandle();
+
+  if (!IsConnected()) {
+    return_info.Set(0, eConnectionStatusNoConnection, ERROR_INVALID_HANDLE);
+    goto finish;
+  }
+
+  // Setup OVERLAPPED event
+  m_overlapped.hEvent = m_event_handles[kBytesAvailableEvent];
+
+  result =
+      ::ReadFile(hInput, dst, static_cast<DWORD>(dst_len), NULL, &m_overlapped);
+  if (result || ::GetLastError() == ERROR_IO_PENDING) {
+    if (!result) {
+      // Operation pending: wait for completion or interrupt
+      DWORD milliseconds =
+          timeout ? static_cast<DWORD>(
+                        std::chrono::duration_cast<std::chrono::milliseconds>(
+                            *timeout)
+                            .count())
+                  : INFINITE;
+
+      DWORD wait_result = ::WaitForMultipleObjects(
+          static_cast<DWORD>(std::size(m_event_handles)), m_event_handles,
+          FALSE, milliseconds);
+
+      switch (wait_result) {
+      case WAIT_OBJECT_0 + kBytesAvailableEvent:
+        break; // Data ready
+      case WAIT_OBJECT_0 + kInterruptEvent:
+        return_info.Set(0, eConnectionStatusInterrupted, 0);
+        goto finish;
+      case WAIT_TIMEOUT:
+        return_info.Set(0, eConnectionStatusTimedOut, 0);
+        goto finish;
+      case WAIT_FAILED:
+        return_info.Set(0, eConnectionStatusError, ::GetLastError());
+        goto finish;
+      }
+    }
+
+    // Get actual number of bytes read
+    if (!::GetOverlappedResult(hInput, &m_overlapped, &bytes_read, FALSE)) {
+      DWORD err = ::GetLastError();
+      if (err == ERROR_HANDLE_EOF || err == ERROR_OPERATION_ABORTED ||
+          err == ERROR_BROKEN_PIPE)
+        return_info.Set(bytes_read, eConnectionStatusEndOfFile, 0);
+ ...
[truncated]

@github-actions
Copy link

🐧 Linux x64 Test Results

The build failed before running any tests. Click on a failure below to see the details.

tools/lldb/source/Host/CMakeFiles/lldbHost.dir/common/PseudoTerminal.cpp.o
FAILED: tools/lldb/source/Host/CMakeFiles/lldbHost.dir/common/PseudoTerminal.cpp.o
sccache /opt/llvm/bin/clang++ -DGTEST_HAS_RTTI=0 -DHAVE_ROUND -D_DEBUG -D_GLIBCXX_ASSERTIONS -D_GLIBCXX_USE_CXX11_ABI=1 -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/lldb/source/Host -I/home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/source/Host -I/home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/include -I/home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/lldb/include -I/home/gha/actions-runner/_work/llvm-project/llvm-project/build/include -I/home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/include -I/usr/include/python3.12 -I/home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/../clang/include -I/home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/lldb/../clang/include -I/home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/source -I/home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/lldb/source -gmlt -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wc++98-compat-extra-semi -Wimplicit-fallthrough -Wcovered-switch-default -Wno-noexcept-type -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wsuggest-override -Wstring-conversion -Wno-pass-failed -Wmisleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -ffunction-sections -fdata-sections -Wno-unknown-pragmas -Wno-strict-aliasing -Wno-vla-extension -O3 -DNDEBUG -std=c++17  -fno-exceptions -funwind-tables -fno-rtti -UNDEBUG -MD -MT tools/lldb/source/Host/CMakeFiles/lldbHost.dir/common/PseudoTerminal.cpp.o -MF tools/lldb/source/Host/CMakeFiles/lldbHost.dir/common/PseudoTerminal.cpp.o.d -o tools/lldb/source/Host/CMakeFiles/lldbHost.dir/common/PseudoTerminal.cpp.o -c /home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/source/Host/common/PseudoTerminal.cpp
In file included from /home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/source/Host/common/PseudoTerminal.cpp:12:
/home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/include/lldb/Host/windows/windows.h:19:10: error: 'windows.h' file not found with <angled> include; use "quotes" instead
19 | #include <windows.h>
|          ^~~~~~~~~~~
|          "windows.h"
1 error generated.

If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the infrastructure label.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants