43 std::vector<std::wstring> env_entries;
44 for (
const auto &KV : env) {
47 env_entries.push_back(std::move(wentry));
49 std::sort(env_entries.begin(), env_entries.end(),
50 [](
const std::wstring &a,
const std::wstring &b) {
51 return _wcsicmp(a.c_str(), b.c_str()) < 0;
54 std::vector<wchar_t> buffer;
55 for (
const auto &env_entry : env_entries) {
56 buffer.insert(buffer.end(), env_entry.begin(), env_entry.end());
57 buffer.push_back(L
'\0');
61 buffer.push_back(L
'\0');
63 buffer.push_back(L
'\0');
88 SIZE_T attributelist_size = 0;
89 InitializeProcThreadAttributeList(
nullptr,
93 startupinfoex.lpAttributeList =
94 static_cast<LPPROC_THREAD_ATTRIBUTE_LIST
>(malloc(attributelist_size));
96 if (!startupinfoex.lpAttributeList)
97 return llvm::mapWindowsError(ERROR_OUTOFMEMORY);
99 if (!InitializeProcThreadAttributeList(startupinfoex.lpAttributeList,
101 0, &attributelist_size)) {
102 free(startupinfoex.lpAttributeList);
103 return llvm::mapWindowsError(GetLastError());
114 STARTUPINFOEXW startupinfoex = {};
115 startupinfoex.StartupInfo.cb =
sizeof(STARTUPINFOEXW);
116 startupinfoex.StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
118 HPCON hPC = launch_info.
GetPTY().GetPseudoTerminalHandle();
119 bool use_pty = hPC != INVALID_HANDLE_VALUE &&
121 launch_info.
GetFlags().
Test(lldb::eLaunchFlagLaunchInTTY);
126 llvm::scope_exit close_handles([&] {
128 ::CloseHandle(stdin_handle);
130 ::CloseHandle(stdout_handle);
132 ::CloseHandle(stderr_handle);
136 if (!attributelist_or_err) {
137 error = attributelist_or_err.getError();
140 llvm::scope_exit delete_attributelist(
141 [&] { DeleteProcThreadAttributeList(startupinfoex.lpAttributeList); });
143 std::vector<HANDLE> inherited_handles;
145 if (!UpdateProcThreadAttribute(startupinfoex.lpAttributeList, 0,
147 sizeof(hPC), NULL, NULL)) {
153 launch_info, startupinfoex, stdout_handle, stderr_handle, stdin_handle);
154 if (!inherited_handles_or_err) {
155 error =
Status(inherited_handles_or_err.getError());
158 inherited_handles = std::move(*inherited_handles_or_err);
161 const char *hide_console_var =
162 getenv(
"LLDB_LAUNCH_INFERIORS_WITHOUT_CONSOLE");
163 if (hide_console_var &&
164 llvm::StringRef(hide_console_var).equals_insensitive(
"true")) {
165 startupinfoex.StartupInfo.dwFlags |= STARTF_USESHOWWINDOW;
166 startupinfoex.StartupInfo.wShowWindow = SW_HIDE;
169 DWORD flags = CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT |
170 EXTENDED_STARTUPINFO_PRESENT;
172 flags |= DEBUG_ONLY_THIS_PROCESS;
174 if (launch_info.
GetFlags().
Test(eLaunchFlagDisableSTDIO) || use_pty)
175 flags &= ~CREATE_NEW_CONSOLE;
177 std::vector<wchar_t> environment =
180 auto wcommandLineOrErr =
182 if (!wcommandLineOrErr) {
186 std::wstring wcommandLine = *wcommandLineOrErr;
190 WCHAR *pwcommandLine = wcommandLine.empty() ? nullptr : &wcommandLine[0];
192 std::wstring wexecutable, wworkingDirectory;
198 PROCESS_INFORMATION pi = {};
200 BOOL result = ::CreateProcessW(
201 wexecutable.c_str(), pwcommandLine, NULL, NULL,
202 !inherited_handles.empty(), flags, environment.data(),
203 wworkingDirectory.size() == 0 ? NULL : wworkingDirectory.c_str(),
204 reinterpret_cast<STARTUPINFOW *
>(&startupinfoex), &pi);
216 ::CloseHandle(pi.hThread);
228 std::vector<HANDLE> inherited_handles;
230 startupinfoex.StartupInfo.hStdError =
231 stderr_handle ? stderr_handle : GetStdHandle(STD_ERROR_HANDLE);
232 startupinfoex.StartupInfo.hStdInput =
233 stdin_handle ? stdin_handle : GetStdHandle(STD_INPUT_HANDLE);
234 startupinfoex.StartupInfo.hStdOutput =
235 stdout_handle ? stdout_handle : GetStdHandle(STD_OUTPUT_HANDLE);
237 if (startupinfoex.StartupInfo.hStdError)
238 inherited_handles.push_back(startupinfoex.StartupInfo.hStdError);
239 if (startupinfoex.StartupInfo.hStdInput)
240 inherited_handles.push_back(startupinfoex.StartupInfo.hStdInput);
241 if (startupinfoex.StartupInfo.hStdOutput)
242 inherited_handles.push_back(startupinfoex.StartupInfo.hStdOutput);
248 inherited_handles.push_back(
reinterpret_cast<HANDLE>(act->
GetFD()));
251 if (inherited_handles.empty())
252 return inherited_handles;
254 if (!UpdateProcThreadAttribute(
255 startupinfoex.lpAttributeList, 0,
256 PROC_THREAD_ATTRIBUTE_HANDLE_LIST, inherited_handles.data(),
257 inherited_handles.size() *
sizeof(
HANDLE),
259 return llvm::mapWindowsError(::GetLastError());
261 return inherited_handles;
268 if (action ==
nullptr)
270 SECURITY_ATTRIBUTES secattr = {};
271 secattr.nLength =
sizeof(SECURITY_ATTRIBUTES);
272 secattr.bInheritHandle = TRUE;
275 DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
278 if (fd == STDIN_FILENO) {
279 access = GENERIC_READ;
280 create = OPEN_EXISTING;
281 flags = FILE_ATTRIBUTE_READONLY;
283 if (fd == STDOUT_FILENO || fd == STDERR_FILENO) {
284 access = GENERIC_WRITE;
285 create = CREATE_ALWAYS;
286 if (fd == STDERR_FILENO)
287 flags = FILE_FLAG_WRITE_THROUGH;
292 llvm::ConvertUTF8toWide(path, wpath);
293 HANDLE result = ::CreateFileW(wpath.c_str(), access, share, &secattr, create,
295 return (result == INVALID_HANDLE_VALUE) ? NULL : result;
llvm::ErrorOr< std::vector< HANDLE > > GetInheritedHandles(const ProcessLaunchInfo &launch_info, STARTUPINFOEXW &startupinfoex, HANDLE stdout_handle=NULL, HANDLE stderr_handle=NULL, HANDLE stdin_handle=NULL)
Get the list of Windows handles that should be inherited by the child process and update STARTUPINFOE...