Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions lldb/include/lldb/Host/windows/ProcessLauncherWindows.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "lldb/Host/ProcessLauncher.h"
#include "lldb/Host/windows/windows.h"
#include "llvm/Support/ErrorOr.h"

namespace lldb_private {

Expand All @@ -23,6 +24,36 @@ class ProcessLauncherWindows : public ProcessLauncher {

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.
///
/// If no handles need to be inherited, an empty vector is returned.
///
/// Otherwise, the function populates the
/// `PROC_THREAD_ATTRIBUTE_HANDLE_LIST` attribute in `startupinfoex` with the
/// 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 stdout_handle
/// \param stderr_handle
/// \param stdin_handle
/// Optional explicit standard stream handles to use for the child process.
///
/// \returns
/// `std::vector<HANDLE>` containing all handles that the child must
/// inherit.
llvm::ErrorOr<std::vector<HANDLE>>
GetInheritedHandles(const ProcessLaunchInfo &launch_info,
STARTUPINFOEXW &startupinfoex,
HANDLE stdout_handle = NULL, HANDLE stderr_handle = NULL,
HANDLE stdin_handle = NULL);
};
}

Expand Down
83 changes: 51 additions & 32 deletions lldb/source/Host/windows/ProcessLauncherWindows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/WindowsError.h"

#include <string>
#include <vector>
Expand Down Expand Up @@ -90,6 +91,9 @@ ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info,
STARTUPINFOW &startupinfo = startupinfoex.StartupInfo;
PROCESS_INFORMATION pi = {};

startupinfo.cb = sizeof(startupinfoex);
startupinfo.dwFlags |= STARTF_USESTDHANDLES;

HANDLE stdin_handle = GetStdioHandle(launch_info, STDIN_FILENO);
HANDLE stdout_handle = GetStdioHandle(launch_info, STDOUT_FILENO);
HANDLE stderr_handle = GetStdioHandle(launch_info, STDERR_FILENO);
Expand All @@ -102,22 +106,13 @@ ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info,
::CloseHandle(stderr_handle);
});

startupinfo.cb = sizeof(startupinfoex);
startupinfo.dwFlags |= STARTF_USESTDHANDLES;
startupinfo.hStdError =
stderr_handle ? stderr_handle : ::GetStdHandle(STD_ERROR_HANDLE);
startupinfo.hStdInput =
stdin_handle ? stdin_handle : ::GetStdHandle(STD_INPUT_HANDLE);
startupinfo.hStdOutput =
stdout_handle ? stdout_handle : ::GetStdHandle(STD_OUTPUT_HANDLE);

std::vector<HANDLE> inherited_handles;
if (startupinfo.hStdError)
inherited_handles.push_back(startupinfo.hStdError);
if (startupinfo.hStdInput)
inherited_handles.push_back(startupinfo.hStdInput);
if (startupinfo.hStdOutput)
inherited_handles.push_back(startupinfo.hStdOutput);
auto inherited_handles_or_err = GetInheritedHandlesW(
launch_info, startupinfoex, stdout_handle, stderr_handle, stdin_handle);
if (!inherited_handles_or_err) {
error = Status(inherited_handles_or_err.getError());
return HostProcess();
}
std::vector<HANDLE> inherited_handles = inherited_handles;

SIZE_T attributelist_size = 0;
InitializeProcThreadAttributeList(/*lpAttributeList=*/nullptr,
Expand All @@ -136,22 +131,6 @@ ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info,
}
auto delete_attributelist = llvm::make_scope_exit(
[&] { DeleteProcThreadAttributeList(startupinfoex.lpAttributeList); });
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()) {
if (!UpdateProcThreadAttribute(
startupinfoex.lpAttributeList, /*dwFlags=*/0,
PROC_THREAD_ATTRIBUTE_HANDLE_LIST, inherited_handles.data(),
inherited_handles.size() * sizeof(HANDLE),
/*lpPreviousValue=*/nullptr, /*lpReturnSize=*/nullptr)) {
error = Status(::GetLastError(), eErrorTypeWin32);
return HostProcess();
}
}

const char *hide_console_var =
getenv("LLDB_LAUNCH_INFERIORS_WITHOUT_CONSOLE");
Expand Down Expand Up @@ -215,6 +194,46 @@ ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info,
return HostProcess(pi.hProcess);
}

llvm::ErrorOr<std::vector<HANDLE>> ProcessLauncherWindows::GetInheritedHandles(
const ProcessLaunchInfo &launch_info, STARTUPINFOEXW &startupinfoex,
HANDLE stdout_handle, HANDLE stderr_handle, HANDLE stdin_handle) {
std::vector<HANDLE> inherited_handles;
STARTUPINFOW startupinfo = startupinfoex.StartupInfo;

startupinfo.hStdError =
stderr_handle ? stderr_handle : GetStdHandle(STD_ERROR_HANDLE);
startupinfo.hStdInput =
stdin_handle ? stdin_handle : GetStdHandle(STD_INPUT_HANDLE);
startupinfo.hStdOutput =
stdout_handle ? stdout_handle : GetStdHandle(STD_OUTPUT_HANDLE);

if (startupinfo.hStdError)
inherited_handles.push_back(startupinfo.hStdError);
if (startupinfo.hStdInput)
inherited_handles.push_back(startupinfo.hStdInput);
if (startupinfo.hStdOutput)
inherited_handles.push_back(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 (inherited_handles.empty())
return inherited_handles;

if (!UpdateProcThreadAttribute(
startupinfoex.lpAttributeList, /*dwFlags=*/0,
PROC_THREAD_ATTRIBUTE_HANDLE_LIST, inherited_handles.data(),
inherited_handles.size() * sizeof(HANDLE),
/*lpPreviousValue=*/nullptr, /*lpReturnSize=*/nullptr))
return llvm::mapWindowsError(::GetLastError());

return inherited_handles;
}

HANDLE
ProcessLauncherWindows::GetStdioHandle(const ProcessLaunchInfo &launch_info,
int fd) {
Expand Down
Loading