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