Program.inc revision 5ced70d8f8458f41e6dc7ac76ad2e7c63ae33664
13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//===- Win32/Program.cpp - Win32 Program Implementation ------- -*- C++ -*-===// 23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// 33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// The LLVM Compiler Infrastructure 43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// 53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// This file is distributed under the University of Illinois Open Source 63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// License. See LICENSE.TXT for details. 73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// 83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//===----------------------------------------------------------------------===// 93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// 103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// This file provides the Win32 specific implementation of the Program class. 113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// 123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//===----------------------------------------------------------------------===// 133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "Windows.h" 153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <cstdio> 163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <malloc.h> 173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <io.h> 183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <fcntl.h> 193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//===----------------------------------------------------------------------===// 213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//=== WARNING: Implementation here must contain only Win32 specific code 223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//=== and must not be UNIX code 233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//===----------------------------------------------------------------------===// 243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 253c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace { 263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry struct Win32ProcessInfo { 273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry HANDLE hProcess; 283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DWORD dwProcessId; 293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 323c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace llvm { 333c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing namespace sys; 343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 353c827367444ee418f129b2c238299f49d3264554Jarkko PoyryProgram::Program() : Data_(0) {} 363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 373c827367444ee418f129b2c238299f49d3264554Jarkko PoyryProgram::~Program() { 383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (Data_) { 393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Win32ProcessInfo* wpi = reinterpret_cast<Win32ProcessInfo*>(Data_); 403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CloseHandle(wpi->hProcess); 413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry delete wpi; 423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Data_ = 0; 433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 463c827367444ee418f129b2c238299f49d3264554Jarkko Poyryunsigned Program::GetPid() const { 473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Win32ProcessInfo* wpi = reinterpret_cast<Win32ProcessInfo*>(Data_); 483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return wpi->dwProcessId; 493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// This function just uses the PATH environment variable to find the program. 523c827367444ee418f129b2c238299f49d3264554Jarkko PoyryPath 533c827367444ee418f129b2c238299f49d3264554Jarkko PoyryProgram::FindProgramByName(const std::string& progName) { 543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Check some degenerate cases 563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (progName.length() == 0) // no program 573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return Path(); 583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Path temp; 593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!temp.set(progName)) // invalid name 603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return Path(); 613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Return paths with slashes verbatim. 623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (progName.find('\\') != std::string::npos || 633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry progName.find('/') != std::string::npos) 643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return temp; 653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // At this point, the file name is valid and does not contain slashes. 673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Let Windows search for it. 683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry char buffer[MAX_PATH]; 693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry char *dummy = NULL; 703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DWORD len = SearchPath(NULL, progName.c_str(), ".exe", MAX_PATH, 713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry buffer, &dummy); 723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // See if it wasn't found. 743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (len == 0) 753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return Path(); 763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // See if we got the entire path. 783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (len < MAX_PATH) 793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return Path(buffer); 803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Buffer was too small; grow and retry. 823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry while (true) { 833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry char *b = reinterpret_cast<char *>(_alloca(len+1)); 843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DWORD len2 = SearchPath(NULL, progName.c_str(), ".exe", len+1, b, &dummy); 853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // It is unlikely the search failed, but it's always possible some file 873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // was added or removed since the last search, so be paranoid... 883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (len2 == 0) 893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return Path(); 90c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry else if (len2 <= len) 91c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry return Path(b); 923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 93c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry len = len2; 943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 95c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry} 96c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry 973c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic HANDLE RedirectIO(const Path *path, int fd, std::string* ErrMsg) { 98c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry HANDLE h; 99c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry if (path == 0) { 100c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry DuplicateHandle(GetCurrentProcess(), (HANDLE)_get_osfhandle(fd), 101c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry GetCurrentProcess(), &h, 1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 0, TRUE, DUPLICATE_SAME_ACCESS); 103c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry return h; 104c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry } 105c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry 106c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry const char *fname; 1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (path->isEmpty()) 108c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry fname = "NUL"; 109c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry else 110c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry fname = path->c_str(); 111c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry 112c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry SECURITY_ATTRIBUTES sa; 113c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry sa.nLength = sizeof(sa); 1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry sa.lpSecurityDescriptor = 0; 1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry sa.bInheritHandle = TRUE; 116c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry 117c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry h = CreateFile(fname, fd ? GENERIC_WRITE : GENERIC_READ, FILE_SHARE_READ, 1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry &sa, fd == 0 ? OPEN_EXISTING : CREATE_ALWAYS, 1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry FILE_ATTRIBUTE_NORMAL, NULL); 1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (h == INVALID_HANDLE_VALUE) { 1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry MakeErrMsg(ErrMsg, std::string(fname) + ": Can't open file for " + 1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (fd ? "input: " : "output: ")); 123c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry } 124c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry 1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return h; 1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/// ArgNeedsQuotes - Check whether argument needs to be quoted when calling 1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/// CreateProcess. 1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool ArgNeedsQuotes(const char *Str) { 1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return Str[0] == '\0' || strpbrk(Str, "\t \"&\'()*<>\\`^|") != 0; 1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 134 135/// ArgLenWithQuotes - Check whether argument needs to be quoted when calling 136/// CreateProcess and returns length of quoted arg with escaped quotes 137static unsigned int ArgLenWithQuotes(const char *Str) { 138 unsigned int len = ArgNeedsQuotes(Str) ? 2 : 0; 139 140 while (*Str != '\0') { 141 if (*Str == '\"') 142 ++len; 143 144 ++len; 145 ++Str; 146 } 147 148 return len; 149} 150 151 152bool 153Program::Execute(const Path& path, 154 const char** args, 155 const char** envp, 156 const Path** redirects, 157 unsigned memoryLimit, 158 std::string* ErrMsg) { 159 if (Data_) { 160 Win32ProcessInfo* wpi = reinterpret_cast<Win32ProcessInfo*>(Data_); 161 CloseHandle(wpi->hProcess); 162 delete wpi; 163 Data_ = 0; 164 } 165 166 if (!path.canExecute()) { 167 if (ErrMsg) 168 *ErrMsg = "program not executable"; 169 return false; 170 } 171 172 // Windows wants a command line, not an array of args, to pass to the new 173 // process. We have to concatenate them all, while quoting the args that 174 // have embedded spaces (or are empty). 175 176 // First, determine the length of the command line. 177 unsigned len = 0; 178 for (unsigned i = 0; args[i]; i++) { 179 len += ArgLenWithQuotes(args[i]) + 1; 180 } 181 182 // Now build the command line. 183 char *command = reinterpret_cast<char *>(_alloca(len+1)); 184 char *p = command; 185 186 for (unsigned i = 0; args[i]; i++) { 187 const char *arg = args[i]; 188 189 bool needsQuoting = ArgNeedsQuotes(arg); 190 if (needsQuoting) 191 *p++ = '"'; 192 193 while (*arg != '\0') { 194 if (*arg == '\"') 195 *p++ = '\\'; 196 197 *p++ = *arg++; 198 } 199 200 if (needsQuoting) 201 *p++ = '"'; 202 *p++ = ' '; 203 } 204 205 *p = 0; 206 207 // The pointer to the environment block for the new process. 208 char *envblock = 0; 209 210 if (envp) { 211 // An environment block consists of a null-terminated block of 212 // null-terminated strings. Convert the array of environment variables to 213 // an environment block by concatenating them. 214 215 // First, determine the length of the environment block. 216 len = 0; 217 for (unsigned i = 0; envp[i]; i++) 218 len += strlen(envp[i]) + 1; 219 220 // Now build the environment block. 221 envblock = reinterpret_cast<char *>(_alloca(len+1)); 222 p = envblock; 223 224 for (unsigned i = 0; envp[i]; i++) { 225 const char *ev = envp[i]; 226 size_t len = strlen(ev) + 1; 227 memcpy(p, ev, len); 228 p += len; 229 } 230 231 *p = 0; 232 } 233 234 // Create a child process. 235 STARTUPINFO si; 236 memset(&si, 0, sizeof(si)); 237 si.cb = sizeof(si); 238 si.hStdInput = INVALID_HANDLE_VALUE; 239 si.hStdOutput = INVALID_HANDLE_VALUE; 240 si.hStdError = INVALID_HANDLE_VALUE; 241 242 if (redirects) { 243 si.dwFlags = STARTF_USESTDHANDLES; 244 245 si.hStdInput = RedirectIO(redirects[0], 0, ErrMsg); 246 if (si.hStdInput == INVALID_HANDLE_VALUE) { 247 MakeErrMsg(ErrMsg, "can't redirect stdin"); 248 return false; 249 } 250 si.hStdOutput = RedirectIO(redirects[1], 1, ErrMsg); 251 if (si.hStdOutput == INVALID_HANDLE_VALUE) { 252 CloseHandle(si.hStdInput); 253 MakeErrMsg(ErrMsg, "can't redirect stdout"); 254 return false; 255 } 256 if (redirects[1] && redirects[2] && *(redirects[1]) == *(redirects[2])) { 257 // If stdout and stderr should go to the same place, redirect stderr 258 // to the handle already open for stdout. 259 DuplicateHandle(GetCurrentProcess(), si.hStdOutput, 260 GetCurrentProcess(), &si.hStdError, 261 0, TRUE, DUPLICATE_SAME_ACCESS); 262 } else { 263 // Just redirect stderr 264 si.hStdError = RedirectIO(redirects[2], 2, ErrMsg); 265 if (si.hStdError == INVALID_HANDLE_VALUE) { 266 CloseHandle(si.hStdInput); 267 CloseHandle(si.hStdOutput); 268 MakeErrMsg(ErrMsg, "can't redirect stderr"); 269 return false; 270 } 271 } 272 } 273 274 PROCESS_INFORMATION pi; 275 memset(&pi, 0, sizeof(pi)); 276 277 fflush(stdout); 278 fflush(stderr); 279 BOOL rc = CreateProcess(path.c_str(), command, NULL, NULL, TRUE, 0, 280 envblock, NULL, &si, &pi); 281 DWORD err = GetLastError(); 282 283 // Regardless of whether the process got created or not, we are done with 284 // the handles we created for it to inherit. 285 CloseHandle(si.hStdInput); 286 CloseHandle(si.hStdOutput); 287 CloseHandle(si.hStdError); 288 289 // Now return an error if the process didn't get created. 290 if (!rc) { 291 SetLastError(err); 292 MakeErrMsg(ErrMsg, std::string("Couldn't execute program '") + 293 path.str() + "'"); 294 return false; 295 } 296 Win32ProcessInfo* wpi = new Win32ProcessInfo; 297 wpi->hProcess = pi.hProcess; 298 wpi->dwProcessId = pi.dwProcessId; 299 Data_ = wpi; 300 301 // Make sure these get closed no matter what. 302 AutoHandle hThread(pi.hThread); 303 304 // Assign the process to a job if a memory limit is defined. 305 AutoHandle hJob(0); 306 if (memoryLimit != 0) { 307 hJob = CreateJobObject(0, 0); 308 bool success = false; 309 if (hJob != 0) { 310 JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli; 311 memset(&jeli, 0, sizeof(jeli)); 312 jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_PROCESS_MEMORY; 313 jeli.ProcessMemoryLimit = uintptr_t(memoryLimit) * 1048576; 314 if (SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, 315 &jeli, sizeof(jeli))) { 316 if (AssignProcessToJobObject(hJob, pi.hProcess)) 317 success = true; 318 } 319 } 320 if (!success) { 321 SetLastError(GetLastError()); 322 MakeErrMsg(ErrMsg, std::string("Unable to set memory limit")); 323 TerminateProcess(pi.hProcess, 1); 324 WaitForSingleObject(pi.hProcess, INFINITE); 325 return false; 326 } 327 } 328 329 return true; 330} 331 332int 333Program::Wait(const Path &path, 334 unsigned secondsToWait, 335 std::string* ErrMsg) { 336 if (Data_ == 0) { 337 MakeErrMsg(ErrMsg, "Process not started!"); 338 return -1; 339 } 340 341 Win32ProcessInfo* wpi = reinterpret_cast<Win32ProcessInfo*>(Data_); 342 HANDLE hProcess = wpi->hProcess; 343 344 // Wait for the process to terminate. 345 DWORD millisecondsToWait = INFINITE; 346 if (secondsToWait > 0) 347 millisecondsToWait = secondsToWait * 1000; 348 349 if (WaitForSingleObject(hProcess, millisecondsToWait) == WAIT_TIMEOUT) { 350 if (!TerminateProcess(hProcess, 1)) { 351 MakeErrMsg(ErrMsg, "Failed to terminate timed-out program."); 352 // -2 indicates a crash or timeout as opposed to failure to execute. 353 return -2; 354 } 355 WaitForSingleObject(hProcess, INFINITE); 356 } 357 358 // Get its exit status. 359 DWORD status; 360 BOOL rc = GetExitCodeProcess(hProcess, &status); 361 DWORD err = GetLastError(); 362 363 if (!rc) { 364 SetLastError(err); 365 MakeErrMsg(ErrMsg, "Failed getting status for program."); 366 // -2 indicates a crash or timeout as opposed to failure to execute. 367 return -2; 368 } 369 370 return status & 0377; 371} 372 373bool 374Program::Kill(std::string* ErrMsg) { 375 if (Data_ == 0) { 376 MakeErrMsg(ErrMsg, "Process not started!"); 377 return true; 378 } 379 380 Win32ProcessInfo* wpi = reinterpret_cast<Win32ProcessInfo*>(Data_); 381 HANDLE hProcess = wpi->hProcess; 382 if (TerminateProcess(hProcess, 1) == 0) { 383 MakeErrMsg(ErrMsg, "The process couldn't be killed!"); 384 return true; 385 } 386 387 return false; 388} 389 390bool Program::ChangeStdinToBinary(){ 391 int result = _setmode( _fileno(stdin), _O_BINARY ); 392 return result == -1; 393} 394 395bool Program::ChangeStdoutToBinary(){ 396 int result = _setmode( _fileno(stdout), _O_BINARY ); 397 return result == -1; 398} 399 400bool Program::ChangeStderrToBinary(){ 401 int result = _setmode( _fileno(stderr), _O_BINARY ); 402 return result == -1; 403} 404 405} 406