[lldb] [llvm] [DRAFT][lldb][windows] add Windows Virtual Console support (PR #168729)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 19 08:06:51 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lldb
Author: Charles Zablit (charles-zablit)
<details>
<summary>Changes</summary>
---
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
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]
``````````
</details>
https://github.com/llvm/llvm-project/pull/168729
More information about the llvm-commits
mailing list