Skip to content

Commit f24275c

Browse files
committed
[lldb] Inherit DuplicateFileAction(HANDLE, HANDLE) handles on windows
This is a follow-up to llvm#126935, which enables passing handles to a child process on windows systems. Unlike on unix-like systems, the handles need to be created with the "inheritable" flag because ...
1 parent ac748d0 commit f24275c

File tree

2 files changed

+47
-11
lines changed

2 files changed

+47
-11
lines changed

lldb/source/Host/windows/ProcessLauncherWindows.cpp

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "lldb/Host/HostProcess.h"
1111
#include "lldb/Host/ProcessLaunchInfo.h"
1212

13+
#include "llvm/ADT/ScopeExit.h"
1314
#include "llvm/ADT/SmallVector.h"
1415
#include "llvm/Support/ConvertUTF.h"
1516
#include "llvm/Support/Program.h"
@@ -65,12 +66,21 @@ ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info,
6566

6667
std::string executable;
6768
std::vector<char> environment;
68-
STARTUPINFO startupinfo = {};
69+
STARTUPINFOEX startupinfoex = {};
70+
STARTUPINFO &startupinfo = startupinfoex.StartupInfo;
6971
PROCESS_INFORMATION pi = {};
7072

7173
HANDLE stdin_handle = GetStdioHandle(launch_info, STDIN_FILENO);
7274
HANDLE stdout_handle = GetStdioHandle(launch_info, STDOUT_FILENO);
7375
HANDLE stderr_handle = GetStdioHandle(launch_info, STDERR_FILENO);
76+
auto close_handles = llvm::make_scope_exit([&] {
77+
if (stdin_handle)
78+
::CloseHandle(stdin_handle);
79+
if (stdout_handle)
80+
::CloseHandle(stdout_handle);
81+
if (stderr_handle)
82+
::CloseHandle(stderr_handle);
83+
});
7484

7585
startupinfo.cb = sizeof(startupinfo);
7686
startupinfo.dwFlags |= STARTF_USESTDHANDLES;
@@ -81,6 +91,40 @@ ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info,
8191
startupinfo.hStdOutput =
8292
stdout_handle ? stdout_handle : ::GetStdHandle(STD_OUTPUT_HANDLE);
8393

94+
size_t attributelist_size = 0;
95+
InitializeProcThreadAttributeList(/*lpAttributeList=*/nullptr,
96+
/*dwAttributeCount=*/1, /*dwFlags=*/0,
97+
&attributelist_size);
98+
99+
startupinfoex.lpAttributeList =
100+
static_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(malloc(attributelist_size));
101+
auto free_attributelist =
102+
llvm::make_scope_exit([&] { free(startupinfoex.lpAttributeList); });
103+
if (!InitializeProcThreadAttributeList(startupinfoex.lpAttributeList,
104+
/*dwAttributeCount=*/1, /*dwFlags=*/0,
105+
&attributelist_size)) {
106+
error = Status(::GetLastError(), eErrorTypeWin32);
107+
return HostProcess();
108+
}
109+
auto delete_attributelist = llvm::make_scope_exit(
110+
[&] { DeleteProcThreadAttributeList(startupinfoex.lpAttributeList); });
111+
std::vector<HANDLE> inherited_handles;
112+
for (size_t i = 0; i < launch_info.GetNumFileActions(); ++i) {
113+
const FileAction *act = launch_info.GetFileActionAtIndex(i);
114+
if (act->GetAction() == FileAction::eFileActionDuplicate &&
115+
act->GetFD() == act->GetActionArgument()) {
116+
inherited_handles.push_back(act->GetFD());
117+
}
118+
}
119+
if (!UpdateProcThreadAttribute(
120+
attributelist_up.get(), /*dwFlags=*/0,
121+
PROC_THREAD_ATTRIBUTE_HANDLE_LIST, inherited_handles.data(),
122+
inherited_handles.size(),
123+
/*lpPreviousValue=*/nullptr, /*lpReturnSize=*/nullptr)) {
124+
error = Status(::GetLastError(), eErrorTypeWin32);
125+
return HostProcess();
126+
}
127+
84128
const char *hide_console_var =
85129
getenv("LLDB_LAUNCH_INFERIORS_WITHOUT_CONSOLE");
86130
if (hide_console_var &&
@@ -89,7 +133,8 @@ ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info,
89133
startupinfo.wShowWindow = SW_HIDE;
90134
}
91135

92-
DWORD flags = CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT;
136+
DWORD flags = CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT |
137+
EXTENDED_STARTUPINFO_PRESENT;
93138
if (launch_info.GetFlags().Test(eLaunchFlagDebug))
94139
flags |= DEBUG_ONLY_THIS_PROCESS;
95140

@@ -131,13 +176,6 @@ ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info,
131176
::CloseHandle(pi.hThread);
132177
}
133178

134-
if (stdin_handle)
135-
::CloseHandle(stdin_handle);
136-
if (stdout_handle)
137-
::CloseHandle(stdout_handle);
138-
if (stderr_handle)
139-
::CloseHandle(stderr_handle);
140-
141179
if (!result)
142180
return HostProcess();
143181

lldb/unittests/Host/HostTest.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@ TEST(Host, LaunchProcessSetsArgv0) {
9090
ASSERT_THAT(exit_status.get_future().get(), 0);
9191
}
9292

93-
#ifdef LLVM_ON_UNIX
9493
TEST(Host, LaunchProcessDuplicatesHandle) {
9594
static constexpr llvm::StringLiteral test_msg("Hello subprocess!");
9695

@@ -125,4 +124,3 @@ TEST(Host, LaunchProcessDuplicatesHandle) {
125124
ASSERT_THAT_EXPECTED(bytes_read, llvm::Succeeded());
126125
ASSERT_EQ(llvm::StringRef(msg, *bytes_read), test_msg);
127126
}
128-
#endif

0 commit comments

Comments
 (0)