41 std::vector<std::wstring> env_entries;
42 for (
const auto &KV : env) {
45 env_entries.push_back(std::move(wentry));
47 std::sort(env_entries.begin(), env_entries.end(),
48 [](
const std::wstring &a,
const std::wstring &b) {
49 return _wcsicmp(a.c_str(), b.c_str()) < 0;
52 std::vector<wchar_t> buffer;
53 for (
const auto &env_entry : env_entries) {
54 buffer.insert(buffer.end(), env_entry.begin(), env_entry.end());
55 buffer.push_back(L
'\0');
59 buffer.push_back(L
'\0');
61 buffer.push_back(L
'\0');
94 SIZE_T attributelist_size = 0;
95 InitializeProcThreadAttributeList(
nullptr,
99 startupinfoex.lpAttributeList =
100 static_cast<LPPROC_THREAD_ATTRIBUTE_LIST
>(malloc(attributelist_size));
102 if (!startupinfoex.lpAttributeList)
103 return llvm::mapWindowsError(ERROR_OUTOFMEMORY);
105 if (!InitializeProcThreadAttributeList(startupinfoex.lpAttributeList,
107 0, &attributelist_size)) {
108 free(startupinfoex.lpAttributeList);
109 return llvm::mapWindowsError(GetLastError());
129 STARTUPINFOEXW startupinfoex = {};
130 startupinfoex.StartupInfo.cb =
sizeof(STARTUPINFOEXW);
131 startupinfoex.StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
138 llvm::scope_exit close_handles([&] {
140 ::CloseHandle(stdin_handle);
142 ::CloseHandle(stdout_handle);
144 ::CloseHandle(stderr_handle);
148 if (!attributelist_or_err) {
149 error = attributelist_or_err.getError();
154 std::vector<HANDLE> inherited_handles;
156 HPCON hPC = launch_info.
GetPTY().GetPseudoTerminalHandle();
162 auto inherited_handles_or_err =
164 stderr_handle, stdin_handle);
165 if (!inherited_handles_or_err) {
166 error =
Status(inherited_handles_or_err.getError());
169 inherited_handles = std::move(*inherited_handles_or_err);
172 const char *hide_console_var =
173 getenv(
"LLDB_LAUNCH_INFERIORS_WITHOUT_CONSOLE");
174 if (hide_console_var &&
175 llvm::StringRef(hide_console_var).equals_insensitive(
"true")) {
176 startupinfoex.StartupInfo.dwFlags |= STARTF_USESHOWWINDOW;
177 startupinfoex.StartupInfo.wShowWindow = SW_HIDE;
180 DWORD flags = CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT |
181 EXTENDED_STARTUPINFO_PRESENT;
183 flags |= DEBUG_ONLY_THIS_PROCESS;
185 if (launch_info.
GetFlags().
Test(eLaunchFlagDisableSTDIO) || use_pty)
186 flags &= ~CREATE_NEW_CONSOLE;
188 std::vector<wchar_t> environment =
191 auto wcommandLineOrErr =
193 if (!wcommandLineOrErr) {
197 std::wstring wcommandLine = *wcommandLineOrErr;
201 WCHAR *pwcommandLine = wcommandLine.empty() ? nullptr : &wcommandLine[0];
203 std::wstring wexecutable, wworkingDirectory;
209 PROCESS_INFORMATION pi = {};
211 BOOL result = ::CreateProcessW(
212 wexecutable.c_str(), pwcommandLine, NULL, NULL,
213 !inherited_handles.empty() || use_pty, flags,
215 wworkingDirectory.size() == 0 ? NULL : wworkingDirectory.c_str(),
216 reinterpret_cast<STARTUPINFOW *
>(&startupinfoex), &pi);
228 ::CloseHandle(pi.hThread);
240 std::vector<HANDLE> inherited_handles;
242 startupinfoex.StartupInfo.hStdError =
243 stderr_handle ? stderr_handle : GetStdHandle(STD_ERROR_HANDLE);
244 startupinfoex.StartupInfo.hStdInput =
245 stdin_handle ? stdin_handle : GetStdHandle(STD_INPUT_HANDLE);
246 startupinfoex.StartupInfo.hStdOutput =
247 stdout_handle ? stdout_handle : GetStdHandle(STD_OUTPUT_HANDLE);
249 if (startupinfoex.StartupInfo.hStdError)
250 inherited_handles.push_back(startupinfoex.StartupInfo.hStdError);
251 if (startupinfoex.StartupInfo.hStdInput)
252 inherited_handles.push_back(startupinfoex.StartupInfo.hStdInput);
253 if (startupinfoex.StartupInfo.hStdOutput)
254 inherited_handles.push_back(startupinfoex.StartupInfo.hStdOutput);
261 inherited_handles.push_back(
reinterpret_cast<HANDLE>(act->
GetFD()));
265 if (inherited_handles.empty())
266 return inherited_handles;
268 if (!UpdateProcThreadAttribute(
269 startupinfoex.lpAttributeList, 0,
270 PROC_THREAD_ATTRIBUTE_HANDLE_LIST, inherited_handles.data(),
271 inherited_handles.size() *
sizeof(
HANDLE),
273 return llvm::mapWindowsError(::GetLastError());
275 return inherited_handles;
293 SECURITY_ATTRIBUTES secattr = {};
294 secattr.nLength =
sizeof(SECURITY_ATTRIBUTES);
295 secattr.bInheritHandle = TRUE;
298 DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
301 if (fd == STDIN_FILENO) {
302 access = GENERIC_READ;
303 create = OPEN_EXISTING;
304 flags = FILE_ATTRIBUTE_READONLY;
306 if (fd == STDOUT_FILENO || fd == STDERR_FILENO) {
307 access = GENERIC_WRITE;
308 create = CREATE_ALWAYS;
309 if (fd == STDERR_FILENO)
310 flags = FILE_FLAG_WRITE_THROUGH;
314 llvm::ConvertUTF8toWide(path, wpath);
315 HANDLE result = ::CreateFileW(wpath.c_str(), access, share, &secattr, create,
317 return (result == INVALID_HANDLE_VALUE) ? NULL : result;
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)
Get the list of Windows handles that should be inherited by the child process and update STARTUPINFOE...