|
18 | 18 | #include "llvm/Config/config.h" |
19 | 19 | #include "llvm/Support/Allocator.h" |
20 | 20 | #include "llvm/Support/Program.h" |
| 21 | +#if defined(_WIN32) |
| 22 | +#include "llvm/Support/Windows/WindowsSupport.h" |
| 23 | +#endif |
21 | 24 |
|
| 25 | +#include <memory> |
22 | 26 | #include <system_error> |
23 | 27 |
|
24 | 28 | #if HAVE_POSIX_SPAWN |
|
29 | 33 | #include <unistd.h> |
30 | 34 | #endif |
31 | 35 |
|
| 36 | +#if defined(_WIN32) |
| 37 | +#define WIN32_LEAN_AND_MEAN |
| 38 | +#include <Windows.h> |
| 39 | +#include <io.h> |
| 40 | +#endif |
| 41 | + |
32 | 42 | using namespace swift; |
33 | 43 |
|
34 | 44 | int swift::ExecuteInPlace(const char *Program, const char **args, |
@@ -175,7 +185,100 @@ swift::ExecuteWithPipe(llvm::StringRef program, |
175 | 185 | #endif |
176 | 186 | close(p1.read); |
177 | 187 | close(p2.write); |
178 | | - return ChildProcessInfo(pid, p1.write, p2.read); |
| 188 | + llvm::sys::ProcessInfo proc; |
| 189 | + proc.Pid = pid; |
| 190 | + return ChildProcessInfo(proc, p1.write, p2.read); |
| 191 | +} |
| 192 | + |
| 193 | +#elif defined(_WIN32) |
| 194 | + |
| 195 | +llvm::ErrorOr<swift::ChildProcessInfo> |
| 196 | +swift::ExecuteWithPipe(llvm::StringRef program, |
| 197 | + llvm::ArrayRef<llvm::StringRef> args, |
| 198 | + llvm::Optional<llvm::ArrayRef<llvm::StringRef>> env) { |
| 199 | + using unique_handle = std::unique_ptr<void, decltype(&CloseHandle)>; |
| 200 | + enum { PI_READ, PI_WRITE }; |
| 201 | + |
| 202 | + unique_handle input[2] = { |
| 203 | + {INVALID_HANDLE_VALUE, CloseHandle}, |
| 204 | + {INVALID_HANDLE_VALUE, CloseHandle}, |
| 205 | + }; |
| 206 | + unique_handle output[2] = { |
| 207 | + {INVALID_HANDLE_VALUE, CloseHandle}, |
| 208 | + {INVALID_HANDLE_VALUE, CloseHandle}, |
| 209 | + }; |
| 210 | + unique_handle error{INVALID_HANDLE_VALUE, CloseHandle}; |
| 211 | + HANDLE hRead = INVALID_HANDLE_VALUE, hWrite = INVALID_HANDLE_VALUE; |
| 212 | + SECURITY_ATTRIBUTES saAttrs{sizeof(SECURITY_ATTRIBUTES), NULL, TRUE}; |
| 213 | + |
| 214 | + if (!CreatePipe(&hRead, &hWrite, &saAttrs, 0)) |
| 215 | + return std::error_code(GetLastError(), std::system_category()); |
| 216 | + output[PI_READ].reset(hRead); |
| 217 | + output[PI_WRITE].reset(hWrite); |
| 218 | + |
| 219 | + if (!SetHandleInformation(output[PI_READ].get(), HANDLE_FLAG_INHERIT, FALSE)) |
| 220 | + return std::error_code(GetLastError(), std::system_category()); |
| 221 | + |
| 222 | + if (!CreatePipe(&hRead, &hWrite, &saAttrs, 0)) |
| 223 | + return std::error_code(GetLastError(), std::system_category()); |
| 224 | + input[PI_READ].reset(hRead); |
| 225 | + input[PI_WRITE].reset(hWrite); |
| 226 | + |
| 227 | + if (!SetHandleInformation(input[PI_WRITE].get(), HANDLE_FLAG_INHERIT, FALSE)) |
| 228 | + return std::error_code(GetLastError(), std::system_category()); |
| 229 | + |
| 230 | + if (!DuplicateHandle(GetCurrentProcess(), GetStdHandle(STD_ERROR_HANDLE), |
| 231 | + GetCurrentProcess(), &hWrite, DUPLICATE_SAME_ACCESS, |
| 232 | + TRUE, DUPLICATE_SAME_ACCESS)) |
| 233 | + return std::error_code(GetLastError(), std::system_category()); |
| 234 | + error.reset(hWrite); |
| 235 | + |
| 236 | + STARTUPINFO si = {0}; |
| 237 | + si.cb = sizeof(si); |
| 238 | + si.hStdInput = input[PI_READ].get(); |
| 239 | + si.hStdOutput = output[PI_WRITE].get(); |
| 240 | + si.hStdError = error.get(); |
| 241 | + si.dwFlags = STARTF_USESTDHANDLES; |
| 242 | + |
| 243 | + llvm::SmallVector<wchar_t, MAX_PATH> executable; |
| 244 | + if (std::error_code ec = llvm::sys::windows::widenPath(program, executable)) |
| 245 | + return ec; |
| 246 | + |
| 247 | + std::vector<StringRef> components; |
| 248 | + components.push_back(program); |
| 249 | + components.assign(args.begin(), args.end()); |
| 250 | + llvm::ErrorOr<std::wstring> commandline = |
| 251 | + llvm::sys::flattenWindowsCommandLine(components); |
| 252 | + if (!commandline) |
| 253 | + return commandline.getError(); |
| 254 | + |
| 255 | + std::vector<wchar_t> command(commandline->size() + 1, 0); |
| 256 | + std::copy(commandline->begin(), commandline->end(), command.begin()); |
| 257 | + |
| 258 | + PROCESS_INFORMATION pi = {0}; |
| 259 | + if (!CreateProcessW(executable.data(), |
| 260 | + command.data(), nullptr, nullptr, TRUE, 0, nullptr, |
| 261 | + nullptr, &si, &pi)) |
| 262 | + return std::error_code(GetLastError(), std::system_category()); |
| 263 | + |
| 264 | + unique_handle hThread{pi.hThread, CloseHandle}; |
| 265 | + unique_handle hProcess{pi.hProcess, CloseHandle}; |
| 266 | + |
| 267 | + int ifd = _open_osfhandle(reinterpret_cast<intptr_t>(input[PI_WRITE].get()), 0); |
| 268 | + if (ifd < 0) |
| 269 | + return std::error_code(errno, std::system_category()); |
| 270 | + input[PI_WRITE].release(); |
| 271 | + |
| 272 | + int ofd = _open_osfhandle(reinterpret_cast<intptr_t>(output[PI_READ].get()), 0); |
| 273 | + if (ofd < 0) { |
| 274 | + _close(ifd); |
| 275 | + return std::error_code(errno, std::system_category()); |
| 276 | + } |
| 277 | + output[PI_READ].release(); |
| 278 | + |
| 279 | + llvm::sys::ProcessInfo proc; |
| 280 | + proc.Process = pi.hProcess; |
| 281 | + return ChildProcessInfo(proc, ifd, ofd); |
179 | 282 | } |
180 | 283 |
|
181 | 284 | #else // HAVE_UNISTD_H |
|
0 commit comments