[Lldb-commits] [lldb] [lldb][windows][NFC] expose ProcessLauncherWindows methods (PR #183579)
Charles Zablit via lldb-commits
lldb-commits at lists.llvm.org
Fri Mar 6 08:35:41 PST 2026
https://github.com/charles-zablit updated https://github.com/llvm/llvm-project/pull/183579
>From 5b31dda22d046600be02806927067063d37ccf75 Mon Sep 17 00:00:00 2001
From: Charles Zablit <c_zablit at apple.com>
Date: Thu, 26 Feb 2026 17:42:04 +0000
Subject: [PATCH 1/4] [lldb][windows][NFC] expose ProcessLauncherWindows
methods
---
.../Host/windows/ProcessLauncherWindows.h | 68 ++++++++++++++++---
.../Host/windows/ProcessLauncherWindows.cpp | 54 +++++++++------
2 files changed, 92 insertions(+), 30 deletions(-)
diff --git a/lldb/include/lldb/Host/windows/ProcessLauncherWindows.h b/lldb/include/lldb/Host/windows/ProcessLauncherWindows.h
index 7f99a46447966..7c72e91dcdb3b 100644
--- a/lldb/include/lldb/Host/windows/ProcessLauncherWindows.h
+++ b/lldb/include/lldb/Host/windows/ProcessLauncherWindows.h
@@ -9,9 +9,15 @@
#ifndef lldb_Host_windows_ProcessLauncherWindows_h_
#define lldb_Host_windows_ProcessLauncherWindows_h_
+#include "lldb/Host/ProcessLaunchInfo.h"
#include "lldb/Host/ProcessLauncher.h"
#include "lldb/Host/windows/windows.h"
-#include "llvm/Support/Error.h"
+#include "llvm/ADT/ScopeExit.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/WindowsError.h"
+
+#include <optional>
namespace lldb_private {
@@ -76,8 +82,6 @@ class ProcessLauncherWindows : public ProcessLauncher {
Status &error) override;
protected:
- HANDLE GetStdioHandle(const ProcessLaunchInfo &launch_info, int fd);
-
/// Get the list of Windows handles that should be inherited by the child
/// process and update `STARTUPINFOEXW` with the handle list.
///
@@ -88,12 +92,12 @@ class ProcessLauncherWindows : public ProcessLauncher {
/// collected handles using `UpdateProcThreadAttribute`. On success, the
/// vector of inherited handles is returned.
///
- /// \param launch_info
- /// The process launch configuration.
- ///
/// \param startupinfoex
/// The extended STARTUPINFO structure for the process being created.
///
+ /// \param launch_info
+ /// The process launch configuration.
+ ///
/// \param stdout_handle
/// \param stderr_handle
/// \param stdin_handle
@@ -102,12 +106,58 @@ class ProcessLauncherWindows : public ProcessLauncher {
/// \returns
/// `std::vector<HANDLE>` containing all handles that the child must
/// inherit.
- llvm::ErrorOr<std::vector<HANDLE>>
- GetInheritedHandles(const ProcessLaunchInfo &launch_info,
- STARTUPINFOEXW &startupinfoex,
+ static llvm::ErrorOr<std::vector<HANDLE>>
+ GetInheritedHandles(STARTUPINFOEXW &startupinfoex,
+ const ProcessLaunchInfo *launch_info = nullptr,
HANDLE stdout_handle = NULL, HANDLE stderr_handle = NULL,
HANDLE stdin_handle = NULL);
+
+ static HANDLE GetStdioHandle(const ProcessLaunchInfo &launch_info, int fd);
+
+ /// Creates a file handle suitable for redirecting stdin, stdout,
+ /// or stderr of a child process.
+ ///
+ /// \param path The file path to open. If empty, returns NULL (no
+ /// redirection).
+ /// \param fd The file descriptor type: STDIN_FILENO, STDOUT_FILENO, or
+ /// STDERR_FILENO.
+ ///
+ /// \return A handle to the opened file, or NULL if the path is empty or the
+ /// file
+ /// cannot be opened (INVALID_HANDLE_VALUE is converted to NULL).
+ ///
+ /// Behavior by file descriptor:
+ /// - STDIN_FILENO: Opens existing file for reading (GENERIC_READ,
+ /// OPEN_EXISTING).
+ /// - STDOUT_FILENO: Creates/truncates file for writing (GENERIC_WRITE,
+ /// CREATE_ALWAYS).
+ /// - STDERR_FILENO: Creates/truncates file for writing with write-through
+ /// (FILE_FLAG_WRITE_THROUGH ensures immediate disk writes,
+ /// bypassing system cache for error messages).
+ ///
+ /// All handles are created with:
+ /// - Inheritance enabled (bInheritHandle = TRUE) so child processes can use
+ /// them.
+ /// - Shared read/write/delete access to allow other processes to access the
+ /// file.
+ static HANDLE GetStdioHandle(const llvm::StringRef path, int fd);
};
+
+/// 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.
+llvm::ErrorOr<std::wstring> GetFlattenedWindowsCommandStringW(Args args);
+
+/// 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.
+llvm::ErrorOr<std::wstring> GetFlattenedWindowsCommandStringW(char *args[]);
}
#endif
diff --git a/lldb/source/Host/windows/ProcessLauncherWindows.cpp b/lldb/source/Host/windows/ProcessLauncherWindows.cpp
index f22e4739ca7b6..924eede01033a 100644
--- a/lldb/source/Host/windows/ProcessLauncherWindows.cpp
+++ b/lldb/source/Host/windows/ProcessLauncherWindows.cpp
@@ -8,11 +8,9 @@
#include "lldb/Host/windows/ProcessLauncherWindows.h"
#include "lldb/Host/HostProcess.h"
-#include "lldb/Host/ProcessLaunchInfo.h"
#include "lldb/Host/windows/PseudoConsole.h"
#include "lldb/Host/windows/windows.h"
-#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Program.h"
@@ -65,14 +63,8 @@ static std::vector<wchar_t> CreateEnvironmentBufferW(const Environment &env) {
return buffer;
}
-/// 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) {
+namespace lldb_private {
+llvm::ErrorOr<std::wstring> GetFlattenedWindowsCommandStringW(Args args) {
if (args.empty())
return L"";
@@ -83,6 +75,16 @@ GetFlattenedWindowsCommandStringW(Args args) {
return llvm::sys::flattenWindowsCommandLine(args_ref);
}
+llvm::ErrorOr<std::wstring> GetFlattenedWindowsCommandStringW(char *args[]) {
+ std::vector<llvm::StringRef> args_ref;
+ for (int i = 0; args[i] != nullptr; ++i) {
+ args_ref.push_back(args[i]);
+ }
+
+ return llvm::sys::flattenWindowsCommandLine(args_ref);
+}
+} // namespace lldb_private
+
llvm::ErrorOr<ProcThreadAttributeList>
ProcThreadAttributeList::Create(STARTUPINFOEXW &startupinfoex) {
SIZE_T attributelist_size = 0;
@@ -153,8 +155,9 @@ ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info,
return HostProcess();
}
} else {
- auto inherited_handles_or_err = GetInheritedHandles(
- launch_info, startupinfoex, stdout_handle, stderr_handle, stdin_handle);
+ auto inherited_handles_or_err =
+ GetInheritedHandles(startupinfoex, &launch_info, stdout_handle,
+ stderr_handle, stdin_handle);
if (!inherited_handles_or_err) {
error = Status(inherited_handles_or_err.getError());
return HostProcess();
@@ -228,7 +231,7 @@ ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info,
}
llvm::ErrorOr<std::vector<HANDLE>> ProcessLauncherWindows::GetInheritedHandles(
- const ProcessLaunchInfo &launch_info, STARTUPINFOEXW &startupinfoex,
+ STARTUPINFOEXW &startupinfoex, const ProcessLaunchInfo *launch_info,
HANDLE stdout_handle, HANDLE stderr_handle, HANDLE stdin_handle) {
std::vector<HANDLE> inherited_handles;
@@ -246,12 +249,13 @@ llvm::ErrorOr<std::vector<HANDLE>> ProcessLauncherWindows::GetInheritedHandles(
if (startupinfoex.StartupInfo.hStdOutput)
inherited_handles.push_back(startupinfoex.StartupInfo.hStdOutput);
- for (size_t i = 0; i < launch_info.GetNumFileActions(); ++i) {
- const FileAction *act = launch_info.GetFileActionAtIndex(i);
- if (act->GetAction() == FileAction::eFileActionDuplicate &&
- act->GetFD() == act->GetActionArgument())
- inherited_handles.push_back(reinterpret_cast<HANDLE>(act->GetFD()));
- }
+ if (launch_info)
+ for (size_t i = 0; i < launch_info->GetNumFileActions(); ++i) {
+ const FileAction *act = launch_info->GetFileActionAtIndex(i);
+ if (act->GetAction() == FileAction::eFileActionDuplicate &&
+ act->GetFD() == act->GetActionArgument())
+ inherited_handles.push_back(reinterpret_cast<HANDLE>(act->GetFD()));
+ }
if (inherited_handles.empty())
return inherited_handles;
@@ -272,6 +276,15 @@ ProcessLauncherWindows::GetStdioHandle(const ProcessLaunchInfo &launch_info,
const FileAction *action = launch_info.GetFileActionForFD(fd);
if (action == nullptr)
return NULL;
+ const std::string path = action->GetFileSpec().GetPath();
+
+ return GetStdioHandle(path, fd);
+}
+
+HANDLE ProcessLauncherWindows::GetStdioHandle(const llvm::StringRef path,
+ int fd) {
+ if (path.empty())
+ return NULL;
SECURITY_ATTRIBUTES secattr = {};
secattr.nLength = sizeof(SECURITY_ATTRIBUTES);
secattr.bInheritHandle = TRUE;
@@ -292,10 +305,9 @@ ProcessLauncherWindows::GetStdioHandle(const ProcessLaunchInfo &launch_info,
flags = FILE_FLAG_WRITE_THROUGH;
}
- const std::string path = action->GetFileSpec().GetPath();
std::wstring wpath;
llvm::ConvertUTF8toWide(path, wpath);
HANDLE result = ::CreateFileW(wpath.c_str(), access, share, &secattr, create,
flags, NULL);
return (result == INVALID_HANDLE_VALUE) ? NULL : result;
-}
+}
\ No newline at end of file
>From 836f8aa04b782b3c83f063ee7d83645620bb90ef Mon Sep 17 00:00:00 2001
From: Charles Zablit <c_zablit at apple.com>
Date: Fri, 6 Mar 2026 15:43:49 +0000
Subject: [PATCH 2/4] fixup! [lldb][windows][NFC] expose ProcessLauncherWindows
methods
---
.../lldb/Host/windows/ProcessLauncherWindows.h | 5 +++--
.../source/Host/windows/ProcessLauncherWindows.cpp | 14 +++++++++-----
2 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/lldb/include/lldb/Host/windows/ProcessLauncherWindows.h b/lldb/include/lldb/Host/windows/ProcessLauncherWindows.h
index 7c72e91dcdb3b..fc2fca532dc60 100644
--- a/lldb/include/lldb/Host/windows/ProcessLauncherWindows.h
+++ b/lldb/include/lldb/Host/windows/ProcessLauncherWindows.h
@@ -149,7 +149,7 @@ class ProcessLauncherWindows : public ProcessLauncher {
///
/// \param args The Args object to flatten.
/// \returns A wide string containing the flattened command line.
-llvm::ErrorOr<std::wstring> GetFlattenedWindowsCommandStringW(Args args);
+llvm::ErrorOr<std::wstring> GetFlattenedWindowsCommandStringW(const Args &args);
/// Flattens an Args object into a Windows command-line wide string.
///
@@ -157,7 +157,8 @@ llvm::ErrorOr<std::wstring> GetFlattenedWindowsCommandStringW(Args args);
///
/// \param args The Args object to flatten.
/// \returns A wide string containing the flattened command line.
-llvm::ErrorOr<std::wstring> GetFlattenedWindowsCommandStringW(char *args[]);
+llvm::ErrorOr<std::wstring>
+GetFlattenedWindowsCommandStringW(llvm::ArrayRef<const char *> args);
}
#endif
diff --git a/lldb/source/Host/windows/ProcessLauncherWindows.cpp b/lldb/source/Host/windows/ProcessLauncherWindows.cpp
index 924eede01033a..b8019588f3906 100644
--- a/lldb/source/Host/windows/ProcessLauncherWindows.cpp
+++ b/lldb/source/Host/windows/ProcessLauncherWindows.cpp
@@ -64,7 +64,8 @@ static std::vector<wchar_t> CreateEnvironmentBufferW(const Environment &env) {
}
namespace lldb_private {
-llvm::ErrorOr<std::wstring> GetFlattenedWindowsCommandStringW(Args args) {
+llvm::ErrorOr<std::wstring>
+GetFlattenedWindowsCommandStringW(const Args &args) {
if (args.empty())
return L"";
@@ -75,11 +76,14 @@ llvm::ErrorOr<std::wstring> GetFlattenedWindowsCommandStringW(Args args) {
return llvm::sys::flattenWindowsCommandLine(args_ref);
}
-llvm::ErrorOr<std::wstring> GetFlattenedWindowsCommandStringW(char *args[]) {
+llvm::ErrorOr<std::wstring>
+GetFlattenedWindowsCommandStringW(llvm::ArrayRef<const char *> args) {
+ if (args.empty())
+ return L"";
+
std::vector<llvm::StringRef> args_ref;
- for (int i = 0; args[i] != nullptr; ++i) {
+ for (int i = 0; args[i] != nullptr; ++i)
args_ref.push_back(args[i]);
- }
return llvm::sys::flattenWindowsCommandLine(args_ref);
}
@@ -310,4 +314,4 @@ HANDLE ProcessLauncherWindows::GetStdioHandle(const llvm::StringRef path,
HANDLE result = ::CreateFileW(wpath.c_str(), access, share, &secattr, create,
flags, NULL);
return (result == INVALID_HANDLE_VALUE) ? NULL : result;
-}
\ No newline at end of file
+}
>From 317d28af4b1ba806715510bb2a00fda2c4d45709 Mon Sep 17 00:00:00 2001
From: Charles Zablit <c_zablit at apple.com>
Date: Fri, 6 Mar 2026 15:45:05 +0000
Subject: [PATCH 3/4] fixup! [lldb][windows][NFC] expose ProcessLauncherWindows
methods
---
lldb/include/lldb/Host/windows/ProcessLauncherWindows.h | 6 ------
1 file changed, 6 deletions(-)
diff --git a/lldb/include/lldb/Host/windows/ProcessLauncherWindows.h b/lldb/include/lldb/Host/windows/ProcessLauncherWindows.h
index fc2fca532dc60..7e1402f9a7d93 100644
--- a/lldb/include/lldb/Host/windows/ProcessLauncherWindows.h
+++ b/lldb/include/lldb/Host/windows/ProcessLauncherWindows.h
@@ -151,12 +151,6 @@ class ProcessLauncherWindows : public ProcessLauncher {
/// \returns A wide string containing the flattened command line.
llvm::ErrorOr<std::wstring> GetFlattenedWindowsCommandStringW(const Args &args);
-/// 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.
llvm::ErrorOr<std::wstring>
GetFlattenedWindowsCommandStringW(llvm::ArrayRef<const char *> args);
}
>From 46bd46b5dbba89b89aa5950b82a39b4c0e7341d7 Mon Sep 17 00:00:00 2001
From: Charles Zablit <c_zablit at apple.com>
Date: Fri, 6 Mar 2026 16:35:27 +0000
Subject: [PATCH 4/4] fixup! [lldb][windows][NFC] expose ProcessLauncherWindows
methods
---
lldb/source/Host/windows/ProcessLauncherWindows.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/lldb/source/Host/windows/ProcessLauncherWindows.cpp b/lldb/source/Host/windows/ProcessLauncherWindows.cpp
index b8019588f3906..fb091eb75d9b8 100644
--- a/lldb/source/Host/windows/ProcessLauncherWindows.cpp
+++ b/lldb/source/Host/windows/ProcessLauncherWindows.cpp
@@ -253,13 +253,14 @@ llvm::ErrorOr<std::vector<HANDLE>> ProcessLauncherWindows::GetInheritedHandles(
if (startupinfoex.StartupInfo.hStdOutput)
inherited_handles.push_back(startupinfoex.StartupInfo.hStdOutput);
- if (launch_info)
+ if (launch_info) {
for (size_t i = 0; i < launch_info->GetNumFileActions(); ++i) {
const FileAction *act = launch_info->GetFileActionAtIndex(i);
if (act->GetAction() == FileAction::eFileActionDuplicate &&
act->GetFD() == act->GetActionArgument())
inherited_handles.push_back(reinterpret_cast<HANDLE>(act->GetFD()));
}
+ }
if (inherited_handles.empty())
return inherited_handles;
More information about the lldb-commits
mailing list