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,14 +66,23 @@ 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);
74-
75- startupinfo.cb = sizeof (startupinfo);
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+ });
84+
85+ startupinfo.cb = sizeof (startupinfoex);
7686 startupinfo.dwFlags |= STARTF_USESTDHANDLES;
7787 startupinfo.hStdError =
7888 stderr_handle ? stderr_handle : ::GetStdHandle (STD_ERROR_HANDLE);
@@ -81,6 +91,48 @@ ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info,
8191 startupinfo.hStdOutput =
8292 stdout_handle ? stdout_handle : ::GetStdHandle (STD_OUTPUT_HANDLE);
8393
94+ std::vector<HANDLE> inherited_handles;
95+ if (startupinfo.hStdError )
96+ inherited_handles.push_back (startupinfo.hStdError );
97+ if (startupinfo.hStdInput )
98+ inherited_handles.push_back (startupinfo.hStdInput );
99+ if (startupinfo.hStdOutput )
100+ inherited_handles.push_back (startupinfo.hStdOutput );
101+
102+ size_t attributelist_size = 0 ;
103+ InitializeProcThreadAttributeList (/* lpAttributeList=*/ nullptr ,
104+ /* dwAttributeCount=*/ 1 , /* dwFlags=*/ 0 ,
105+ &attributelist_size);
106+
107+ startupinfoex.lpAttributeList =
108+ static_cast <LPPROC_THREAD_ATTRIBUTE_LIST>(malloc (attributelist_size));
109+ auto free_attributelist =
110+ llvm::make_scope_exit ([&] { free (startupinfoex.lpAttributeList ); });
111+ if (!InitializeProcThreadAttributeList (startupinfoex.lpAttributeList ,
112+ /* dwAttributeCount=*/ 1 , /* dwFlags=*/ 0 ,
113+ &attributelist_size)) {
114+ error = Status (::GetLastError (), eErrorTypeWin32);
115+ return HostProcess ();
116+ }
117+ auto delete_attributelist = llvm::make_scope_exit (
118+ [&] { DeleteProcThreadAttributeList (startupinfoex.lpAttributeList ); });
119+ for (size_t i = 0 ; i < launch_info.GetNumFileActions (); ++i) {
120+ const FileAction *act = launch_info.GetFileActionAtIndex (i);
121+ if (act->GetAction () == FileAction::eFileActionDuplicate &&
122+ act->GetFD () == act->GetActionArgument ())
123+ inherited_handles.push_back (reinterpret_cast <HANDLE>(act->GetFD ()));
124+ }
125+ if (!inherited_handles.empty ()) {
126+ if (!UpdateProcThreadAttribute (
127+ startupinfoex.lpAttributeList , /* dwFlags=*/ 0 ,
128+ PROC_THREAD_ATTRIBUTE_HANDLE_LIST, inherited_handles.data (),
129+ inherited_handles.size () * sizeof (HANDLE),
130+ /* lpPreviousValue=*/ nullptr , /* lpReturnSize=*/ nullptr )) {
131+ error = Status (::GetLastError (), eErrorTypeWin32);
132+ return HostProcess ();
133+ }
134+ }
135+
84136 const char *hide_console_var =
85137 getenv (" LLDB_LAUNCH_INFERIORS_WITHOUT_CONSOLE" );
86138 if (hide_console_var &&
@@ -89,7 +141,8 @@ ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info,
89141 startupinfo.wShowWindow = SW_HIDE;
90142 }
91143
92- DWORD flags = CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT;
144+ DWORD flags = CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT |
145+ EXTENDED_STARTUPINFO_PRESENT;
93146 if (launch_info.GetFlags ().Test (eLaunchFlagDebug))
94147 flags |= DEBUG_ONLY_THIS_PROCESS;
95148
@@ -114,9 +167,10 @@ ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info,
114167 WCHAR *pwcommandLine = wcommandLine.empty () ? nullptr : &wcommandLine[0 ];
115168
116169 BOOL result = ::CreateProcessW (
117- wexecutable.c_str (), pwcommandLine, NULL , NULL , TRUE , flags, env_block,
170+ wexecutable.c_str (), pwcommandLine, NULL , NULL ,
171+ /* bInheritHandles=*/ !inherited_handles.empty (), flags, env_block,
118172 wworkingDirectory.size () == 0 ? NULL : wworkingDirectory.c_str (),
119- &startupinfo , &pi);
173+ reinterpret_cast <STARTUPINFO *>(&startupinfoex) , &pi);
120174
121175 if (!result) {
122176 // Call GetLastError before we make any other system calls.
@@ -131,13 +185,6 @@ ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info,
131185 ::CloseHandle (pi.hThread);
132186 }
133187
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-
141188 if (!result)
142189 return HostProcess ();
143190
0 commit comments