[llvm-commits] [llvm] r76340 - in /llvm/trunk: include/llvm/System/Program.h lib/System/Program.cpp lib/System/Unix/Program.inc lib/System/Win32/Program.inc
Mikhail Glushenkov
foldr at codedgers.com
Sat Jul 18 14:43:13 PDT 2009
Author: foldr
Date: Sat Jul 18 16:43:12 2009
New Revision: 76340
URL: http://llvm.org/viewvc/llvm-project?rev=76340&view=rev
Log:
Remove duplication in Program::Execute{And,No}Wait.
Implemented by moving the code out of static functions into methods of Program
class.
Modified:
llvm/trunk/include/llvm/System/Program.h
llvm/trunk/lib/System/Program.cpp
llvm/trunk/lib/System/Unix/Program.inc
llvm/trunk/lib/System/Win32/Program.inc
Modified: llvm/trunk/include/llvm/System/Program.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/System/Program.h?rev=76340&r1=76339&r2=76340&view=diff
==============================================================================
--- llvm/trunk/include/llvm/System/Program.h (original)
+++ llvm/trunk/include/llvm/System/Program.h Sat Jul 18 16:43:12 2009
@@ -19,6 +19,9 @@
namespace llvm {
namespace sys {
+ // TODO: Add operations to communicate with the process, redirect its I/O,
+ // etc.
+
/// This class provides an abstraction for programs that are executable by the
/// operating system. It provides a platform generic way to find executable
/// programs from the path and to execute them in various ways. The sys::Path
@@ -26,104 +29,112 @@
/// @since 1.4
/// @brief An abstraction for finding and executing programs.
class Program {
+ unsigned Pid_;
+
+ // Noncopyable.
+ Program(const Program& other);
+ Program& operator=(const Program& other);
+
/// @name Methods
/// @{
- public:
- /// This static constructor (factory) will attempt to locate a program in
- /// the operating system's file system using some pre-determined set of
- /// locations to search (e.g. the PATH on Unix).
- /// @returns A Path object initialized to the path of the program or a
- /// Path object that is empty (invalid) if the program could not be found.
- /// @throws nothing
- /// @brief Construct a Program by finding it by name.
- static Path FindProgramByName(const std::string& name);
-
- /// This function executes the program using the \p arguments provided and
- /// waits for the program to exit. This function will block the current
- /// program until the invoked program exits. The invoked program will
- /// inherit the stdin, stdout, and stderr file descriptors, the
- /// environment and other configuration settings of the invoking program.
- /// If Path::executable() does not return true when this function is
- /// called then a std::string is thrown.
- /// @returns an integer result code indicating the status of the program.
- /// A zero or positive value indicates the result code of the program. A
- /// negative value is the signal number on which it terminated.
- /// @see FindProgrambyName
- /// @brief Executes the program with the given set of \p args.
- static int ExecuteAndWait(
- const Path& path, ///< sys::Path object providing the path of the
- ///< program to be executed. It is presumed this is the result of
- ///< the FindProgramByName method.
- const char** args, ///< A vector of strings that are passed to the
- ///< program. The first element should be the name of the program.
- ///< The list *must* be terminated by a null char* entry.
- const char ** env = 0, ///< An optional vector of strings to use for
- ///< the program's environment. If not provided, the current program's
- ///< environment will be used.
- const sys::Path** redirects = 0, ///< An optional array of pointers to
- ///< Paths. If the array is null, no redirection is done. The array
- ///< should have a size of at least three. If the pointer in the array
- ///< are not null, then the inferior process's stdin(0), stdout(1),
- ///< and stderr(2) will be redirected to the corresponding Paths.
- ///< When an empty Path is passed in, the corresponding file
- ///< descriptor will be disconnected (ie, /dev/null'd) in a portable
- ///< way.
- unsigned secondsToWait = 0, ///< If non-zero, this specifies the amount
- ///< of time to wait for the child process to exit. If the time
- ///< expires, the child is killed and this call returns. If zero,
- ///< this function will wait until the child finishes or forever if
- ///< it doesn't.
- unsigned memoryLimit = 0, ///< If non-zero, this specifies max. amount
- ///< of memory can be allocated by process. If memory usage will be
- ///< higher limit, the child is killed and this call returns. If zero
- ///< - no memory limit.
- std::string* ErrMsg = 0 ///< If non-zero, provides a pointer to a string
- ///< instance in which error messages will be returned. If the string
- ///< is non-empty upon return an error occurred while invoking the
- ///< program.
+ public:
+
+ Program() : Pid_(0)
+ {}
+
+ /// This function executes the program using the \p arguments provided. The
+ /// invoked program will inherit the stdin, stdout, and stderr file
+ /// descriptors, the environment and other configuration settings of the
+ /// invoking program. If Path::executable() does not return true when this
+ /// function is called then a std::string is thrown.
+ /// @returns false in case of error, true otherwise.
+ /// @see FindProgramByName
+ /// @brief Executes the program with the given set of \p args.
+ bool Execute
+ ( const Path& path, ///< sys::Path object providing the path of the
+ ///< program to be executed. It is presumed this is the result of
+ ///< the FindProgramByName method.
+ const char** args, ///< A vector of strings that are passed to the
+ ///< program. The first element should be the name of the program.
+ ///< The list *must* be terminated by a null char* entry.
+ const char ** env = 0, ///< An optional vector of strings to use for
+ ///< the program's environment. If not provided, the current program's
+ ///< environment will be used.
+ const sys::Path** redirects = 0, ///< An optional array of pointers to
+ ///< Paths. If the array is null, no redirection is done. The array
+ ///< should have a size of at least three. If the pointer in the array
+ ///< are not null, then the inferior process's stdin(0), stdout(1),
+ ///< and stderr(2) will be redirected to the corresponding Paths.
+ ///< When an empty Path is passed in, the corresponding file
+ ///< descriptor will be disconnected (ie, /dev/null'd) in a portable
+ ///< way.
+ unsigned memoryLimit = 0, ///< If non-zero, this specifies max. amount
+ ///< of memory can be allocated by process. If memory usage will be
+ ///< higher limit, the child is killed and this call returns. If zero
+ ///< - no memory limit.
+ std::string* ErrMsg = 0 ///< If non-zero, provides a pointer to a string
+ ///< instance in which error messages will be returned. If the string
+ ///< is non-empty upon return an error occurred while invoking the
+ ///< program.
+ );
+
+ /// This function waits for the program to exit. This function will block
+ /// the current program until the invoked program exits.
+ /// @returns an integer result code indicating the status of the program.
+ /// A zero or positive value indicates the result code of the program. A
+ /// negative value is the signal number on which it terminated.
+ /// @see Execute
+ /// @brief Waits for the program to exit.
+ int Wait
+ ( unsigned secondsToWait = 0, ///< If non-zero, this specifies the amount
+ ///< of time to wait for the child process to exit. If the time
+ ///< expires, the child is killed and this call returns. If zero,
+ ///< this function will wait until the child finishes or forever if
+ ///< it doesn't.
+ std::string* ErrMsg = 0 ///< If non-zero, provides a pointer to a string
+ ///< instance in which error messages will be returned. If the string
+ ///< is non-empty upon return an error occurred while invoking the
+ ///< program.
);
- // These methods change the specified standard stream (stdin or stdout) to
- // binary mode. They return true if an error occurred
- static bool ChangeStdinToBinary();
- static bool ChangeStdoutToBinary();
+
+ /// This static constructor (factory) will attempt to locate a program in
+ /// the operating system's file system using some pre-determined set of
+ /// locations to search (e.g. the PATH on Unix).
+ /// @returns A Path object initialized to the path of the program or a
+ /// Path object that is empty (invalid) if the program could not be found.
+ /// @throws nothing
+ /// @brief Construct a Program by finding it by name.
+ static Path FindProgramByName(const std::string& name);
+
+ // These methods change the specified standard stream (stdin or stdout) to
+ // binary mode. They return true if an error occurred
+ static bool ChangeStdinToBinary();
+ static bool ChangeStdoutToBinary();
+
+ /// A convenience function equivalent to Program prg; prg.Execute(..);
+ /// prg.Wait(..);
+ /// @throws nothing
+ /// @see Execute, Wait
+ static int ExecuteAndWait(const Path& path,
+ const char** args,
+ const char ** env = 0,
+ const sys::Path** redirects = 0,
+ unsigned secondsToWait = 0,
+ unsigned memoryLimit = 0,
+ std::string* ErrMsg = 0);
+
+ /// A convenience function equivalent to Program prg; prg.Execute(..);
+ /// @throws nothing
+ /// @see Execute
+ static void ExecuteNoWait(const Path& path,
+ const char** args,
+ const char ** env = 0,
+ const sys::Path** redirects = 0,
+ unsigned memoryLimit = 0,
+ std::string* ErrMsg = 0);
+
/// @}
- /// This function executes the program using the \p arguments provided and
- /// waits for the program to exit. This function will block the current
- /// program until the invoked program exits. The invoked program will
- /// inherit the stdin, stdout, and stderr file descriptors, the
- /// environment and other configuration settings of the invoking program.
- /// If Path::executable() does not return true when this function is
- /// called then a std::string is thrown.
- /// @returns an integer result code indicating the status of the program.
- /// A zero or positive value indicates the result code of the program. A
- /// negative value is the signal number on which it terminated.
- /// @see FindProgrambyName
- /// @brief Executes the program with the given set of \p args.
- static void ExecuteNoWait(
- const Path& path, ///< sys::Path object providing the path of the
- ///< program to be executed. It is presumed this is the result of
- ///< the FindProgramByName method.
- const char** args, ///< A vector of strings that are passed to the
- ///< program. The first element should be the name of the program.
- ///< The list *must* be terminated by a null char* entry.
- const char ** env = 0, ///< An optional vector of strings to use for
- ///< the program's environment. If not provided, the current program's
- ///< environment will be used.
- const sys::Path** redirects = 0, ///< An optional array of pointers to
- ///< Paths. If the array is null, no redirection is done. The array
- ///< should have a size of at least three. If the pointer in the array
- ///< are not null, then the inferior process's stdin(0), stdout(1),
- ///< and stderr(2) will be redirected to the corresponding Paths.
- unsigned memoryLimit = 0, ///< If non-zero, this specifies max. amount
- ///< of memory can be allocated by process. If memory usage will be
- ///< higher limit, the child is killed and this call returns. If zero -
- ///< no memory limit.
- std::string* ErrMsg = 0 ///< If non-zero, provides a pointer to a string
- ///< instance in which error messages will be returned. If the string
- ///< is non-empty upon return an error occurred while invoking the
- ///< program.
- );
};
}
}
Modified: llvm/trunk/lib/System/Program.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/System/Program.cpp?rev=76340&r1=76339&r2=76340&view=diff
==============================================================================
--- llvm/trunk/lib/System/Program.cpp (original)
+++ llvm/trunk/lib/System/Program.cpp Sat Jul 18 16:43:12 2009
@@ -22,6 +22,33 @@
//=== independent code.
//===----------------------------------------------------------------------===//
+int
+Program::ExecuteAndWait(const Path& path,
+ const char** args,
+ const char** envp,
+ const Path** redirects,
+ unsigned secondsToWait,
+ unsigned memoryLimit,
+ std::string* ErrMsg) {
+ Program prg;
+ if (prg.Execute(path, args, envp, redirects, memoryLimit, ErrMsg))
+ return prg.Wait(secondsToWait, ErrMsg);
+ else
+ return -1;
+}
+
+void
+Program::ExecuteNoWait(const Path& path,
+ const char** args,
+ const char** envp,
+ const Path** redirects,
+ unsigned memoryLimit,
+ std::string* ErrMsg) {
+ Program prg;
+ prg.Execute(path, args, envp, redirects, memoryLimit, ErrMsg);
+}
+
+
}
// Include the platform-specific parts of this class.
Modified: llvm/trunk/lib/System/Unix/Program.inc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/System/Unix/Program.inc?rev=76340&r1=76339&r2=76340&view=diff
==============================================================================
--- llvm/trunk/lib/System/Unix/Program.inc (original)
+++ llvm/trunk/lib/System/Unix/Program.inc Sat Jul 18 16:43:12 2009
@@ -142,49 +142,47 @@
#endif
}
-int
-Program::ExecuteAndWait(const Path& path,
- const char** args,
- const char** envp,
- const Path** redirects,
- unsigned secondsToWait,
- unsigned memoryLimit,
- std::string* ErrMsg)
+bool
+Program::Execute(const Path& path,
+ const char** args,
+ const char** envp,
+ const Path** redirects,
+ unsigned memoryLimit,
+ std::string* ErrMsg)
{
if (!path.canExecute()) {
if (ErrMsg)
*ErrMsg = path.toString() + " is not executable";
- return -1;
+ return false;
}
-#ifdef HAVE_SYS_WAIT_H
// Create a child process.
int child = fork();
switch (child) {
// An error occured: Return to the caller.
case -1:
MakeErrMsg(ErrMsg, "Couldn't fork");
- return -1;
+ return false;
// Child process: Execute the program.
case 0: {
// Redirect file descriptors...
if (redirects) {
// Redirect stdin
- if (RedirectIO(redirects[0], 0, ErrMsg)) { return -1; }
+ if (RedirectIO(redirects[0], 0, ErrMsg)) { return false; }
// Redirect stdout
- if (RedirectIO(redirects[1], 1, ErrMsg)) { return -1; }
+ if (RedirectIO(redirects[1], 1, ErrMsg)) { return false; }
if (redirects[1] && redirects[2] &&
*(redirects[1]) == *(redirects[2])) {
// If stdout and stderr should go to the same place, redirect stderr
// to the FD already open for stdout.
if (-1 == dup2(1,2)) {
MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout");
- return -1;
+ return false;
}
} else {
// Just redirect stderr
- if (RedirectIO(redirects[2], 2, ErrMsg)) { return -1; }
+ if (RedirectIO(redirects[2], 2, ErrMsg)) { return false; }
}
}
@@ -214,8 +212,23 @@
fsync(1);
fsync(2);
+ Pid_ = child;
+
+ return true;
+}
+
+int
+Program::Wait(unsigned secondsToWait,
+ std::string* ErrMsg)
+{
+#ifdef HAVE_SYS_WAIT_H
struct sigaction Act, Old;
+ if (Pid_ == 0) {
+ MakeErrMsg(ErrMsg, "Process not started!");
+ return -1;
+ }
+
// Install a timeout handler.
if (secondsToWait) {
Timeout = false;
@@ -229,6 +242,7 @@
// Parent process: Wait for the child process to terminate.
int status;
+ int child = this->Pid_;
while (wait(&status) != child)
if (secondsToWait && errno == EINTR) {
// Kill the child.
@@ -274,78 +288,6 @@
}
-void
-Program::ExecuteNoWait(const Path& path,
- const char** args,
- const char** envp,
- const Path** redirects,
- unsigned memoryLimit,
- std::string* ErrMsg)
-{
- if (!path.canExecute()) {
- if (ErrMsg)
- *ErrMsg = path.toString() + " is not executable";
- return;
- }
-
- // Create a child process.
- int child = fork();
- switch (child) {
- // An error occured: Return to the caller.
- case -1:
- MakeErrMsg(ErrMsg, "Couldn't fork");
- return;
-
- // Child process: Execute the program.
- case 0: {
- // Redirect file descriptors...
- if (redirects) {
- // Redirect stdin
- if (RedirectIO(redirects[0], 0, ErrMsg)) { return; }
- // Redirect stdout
- if (RedirectIO(redirects[1], 1, ErrMsg)) { return; }
- if (redirects[1] && redirects[2] &&
- *(redirects[1]) == *(redirects[2])) {
- // If stdout and stderr should go to the same place, redirect stderr
- // to the FD already open for stdout.
- if (-1 == dup2(1,2)) {
- MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout");
- return;
- }
- } else {
- // Just redirect stderr
- if (RedirectIO(redirects[2], 2, ErrMsg)) { return; }
- }
- }
-
- // Set memory limits
- if (memoryLimit!=0) {
- SetMemoryLimits(memoryLimit);
- }
-
- // Execute!
- if (envp != 0)
- execve (path.c_str(), (char**)args, (char**)envp);
- else
- execv (path.c_str(), (char**)args);
- // If the execve() failed, we should exit and let the parent pick up
- // our non-zero exit status.
- exit (errno);
- }
-
- // Parent process: Break out of the switch to do our processing.
- default:
- break;
- }
-
- // Make sure stderr and stdout have been flushed
- std::cerr << std::flush;
- std::cout << std::flush;
- fsync(1);
- fsync(2);
-
-}
-
bool Program::ChangeStdinToBinary(){
// Do nothing, as Unix doesn't differentiate between text and binary.
return false;
Modified: llvm/trunk/lib/System/Win32/Program.inc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/System/Win32/Program.inc?rev=76340&r1=76339&r2=76340&view=diff
==============================================================================
--- llvm/trunk/lib/System/Win32/Program.inc (original)
+++ llvm/trunk/lib/System/Win32/Program.inc Sat Jul 18 16:43:12 2009
@@ -109,18 +109,17 @@
DWORD cbJobObjectInfoLength);
#endif
-int
-Program::ExecuteAndWait(const Path& path,
- const char** args,
- const char** envp,
- const Path** redirects,
- unsigned secondsToWait,
- unsigned memoryLimit,
- std::string* ErrMsg) {
+bool
+Program::Execute(const Path& path,
+ const char** args,
+ const char** envp,
+ const Path** redirects,
+ unsigned memoryLimit,
+ std::string* ErrMsg) {
if (!path.canExecute()) {
if (ErrMsg)
*ErrMsg = "program not executable";
- return -1;
+ return false;
}
// Windows wants a command line, not an array of args, to pass to the new
@@ -195,13 +194,13 @@
si.hStdInput = RedirectIO(redirects[0], 0, ErrMsg);
if (si.hStdInput == INVALID_HANDLE_VALUE) {
MakeErrMsg(ErrMsg, "can't redirect stdin");
- return -1;
+ return false;
}
si.hStdOutput = RedirectIO(redirects[1], 1, ErrMsg);
if (si.hStdOutput == INVALID_HANDLE_VALUE) {
CloseHandle(si.hStdInput);
MakeErrMsg(ErrMsg, "can't redirect stdout");
- return -1;
+ return false;
}
if (redirects[1] && redirects[2] && *(redirects[1]) == *(redirects[2])) {
// If stdout and stderr should go to the same place, redirect stderr
@@ -216,7 +215,7 @@
CloseHandle(si.hStdInput);
CloseHandle(si.hStdOutput);
MakeErrMsg(ErrMsg, "can't redirect stderr");
- return -1;
+ return false;
}
}
}
@@ -242,8 +241,9 @@
SetLastError(err);
MakeErrMsg(ErrMsg, std::string("Couldn't execute program '") +
path.toString() + "'");
- return -1;
+ return false;
}
+ Pid_ = pi.dwProcessId;
// Make sure these get closed no matter what.
AutoHandle hProcess(pi.hProcess);
@@ -270,204 +270,50 @@
MakeErrMsg(ErrMsg, std::string("Unable to set memory limit"));
TerminateProcess(pi.hProcess, 1);
WaitForSingleObject(pi.hProcess, INFINITE);
- return -1;
+ return false;
}
}
- // Wait for it to terminate.
+ return true;
+}
+
+int
+Program::Wait(unsigned secondsToWait,
+ std::string* ErrMsg) {
+ if (Pid_ == 0) {
+ MakeErrMsg(ErrMsg, "Process not started!");
+ return -1;
+ }
+
+ AutoHandle hProcess = OpenProcess(SYNCHRONIZE, FALSE, Pid_);
+
+ // Wait for the process to terminate.
DWORD millisecondsToWait = INFINITE;
if (secondsToWait > 0)
millisecondsToWait = secondsToWait * 1000;
- if (WaitForSingleObject(pi.hProcess, millisecondsToWait) == WAIT_TIMEOUT) {
- if (!TerminateProcess(pi.hProcess, 1)) {
- MakeErrMsg(ErrMsg, std::string("Failed to terminate timed-out program '")
- + path.toString() + "'");
+ if (WaitForSingleObject(hProcess, millisecondsToWait) == WAIT_TIMEOUT) {
+ if (!TerminateProcess(hProcess, 1)) {
+ MakeErrMsg(ErrMsg, "Failed to terminate timed-out program.");
return -1;
}
- WaitForSingleObject(pi.hProcess, INFINITE);
+ WaitForSingleObject(hProcess, INFINITE);
}
// Get its exit status.
DWORD status;
- rc = GetExitCodeProcess(pi.hProcess, &status);
- err = GetLastError();
+ BOOL rc = GetExitCodeProcess(hProcess, &status);
+ DWORD err = GetLastError();
if (!rc) {
SetLastError(err);
- MakeErrMsg(ErrMsg, std::string("Failed getting status for program '") +
- path.toString() + "'");
+ MakeErrMsg(ErrMsg, "Failed getting status for program.");
return -1;
}
return status;
}
-void
-Program::ExecuteNoWait(const Path& path,
- const char** args,
- const char** envp,
- const Path** redirects,
- unsigned memoryLimit,
- std::string* ErrMsg) {
- if (!path.canExecute()) {
- if (ErrMsg)
- *ErrMsg = "program not executable";
- return;
- }
-
- // Windows wants a command line, not an array of args, to pass to the new
- // process. We have to concatenate them all, while quoting the args that
- // have embedded spaces.
-
- // First, determine the length of the command line.
- unsigned len = 0;
- for (unsigned i = 0; args[i]; i++) {
- len += strlen(args[i]) + 1;
- if (strchr(args[i], ' '))
- len += 2;
- }
-
- // Now build the command line.
- char *command = reinterpret_cast<char *>(_alloca(len+1));
- char *p = command;
-
- for (unsigned i = 0; args[i]; i++) {
- const char *arg = args[i];
- size_t len = strlen(arg);
- bool needsQuoting = strchr(arg, ' ') != 0;
- if (needsQuoting)
- *p++ = '"';
- memcpy(p, arg, len);
- p += len;
- if (needsQuoting)
- *p++ = '"';
- *p++ = ' ';
- }
-
- *p = 0;
-
- // The pointer to the environment block for the new process.
- char *envblock = 0;
-
- if (envp) {
- // An environment block consists of a null-terminated block of
- // null-terminated strings. Convert the array of environment variables to
- // an environment block by concatenating them.
-
- // First, determine the length of the environment block.
- len = 0;
- for (unsigned i = 0; envp[i]; i++)
- len += strlen(envp[i]) + 1;
-
- // Now build the environment block.
- envblock = reinterpret_cast<char *>(_alloca(len+1));
- p = envblock;
-
- for (unsigned i = 0; envp[i]; i++) {
- const char *ev = envp[i];
- size_t len = strlen(ev) + 1;
- memcpy(p, ev, len);
- p += len;
- }
-
- *p = 0;
- }
-
- // Create a child process.
- STARTUPINFO si;
- memset(&si, 0, sizeof(si));
- si.cb = sizeof(si);
- si.hStdInput = INVALID_HANDLE_VALUE;
- si.hStdOutput = INVALID_HANDLE_VALUE;
- si.hStdError = INVALID_HANDLE_VALUE;
-
- if (redirects) {
- si.dwFlags = STARTF_USESTDHANDLES;
-
- si.hStdInput = RedirectIO(redirects[0], 0, ErrMsg);
- if (si.hStdInput == INVALID_HANDLE_VALUE) {
- MakeErrMsg(ErrMsg, "can't redirect stdin");
- return;
- }
- si.hStdOutput = RedirectIO(redirects[1], 1, ErrMsg);
- if (si.hStdOutput == INVALID_HANDLE_VALUE) {
- CloseHandle(si.hStdInput);
- MakeErrMsg(ErrMsg, "can't redirect stdout");
- return;
- }
- if (redirects[1] && redirects[2] && *(redirects[1]) == *(redirects[2])) {
- // If stdout and stderr should go to the same place, redirect stderr
- // to the handle already open for stdout.
- DuplicateHandle(GetCurrentProcess(), si.hStdOutput,
- GetCurrentProcess(), &si.hStdError,
- 0, TRUE, DUPLICATE_SAME_ACCESS);
- } else {
- // Just redirect stderr
- si.hStdError = RedirectIO(redirects[2], 2, ErrMsg);
- if (si.hStdError == INVALID_HANDLE_VALUE) {
- CloseHandle(si.hStdInput);
- CloseHandle(si.hStdOutput);
- MakeErrMsg(ErrMsg, "can't redirect stderr");
- return;
- }
- }
- }
-
- PROCESS_INFORMATION pi;
- memset(&pi, 0, sizeof(pi));
-
- fflush(stdout);
- fflush(stderr);
- BOOL rc = CreateProcess(path.c_str(), command, NULL, NULL, TRUE, 0,
- envblock, NULL, &si, &pi);
- DWORD err = GetLastError();
-
- // Regardless of whether the process got created or not, we are done with
- // the handles we created for it to inherit.
- CloseHandle(si.hStdInput);
- CloseHandle(si.hStdOutput);
- CloseHandle(si.hStdError);
-
- // Now return an error if the process didn't get created.
- if (!rc)
- {
- SetLastError(err);
- MakeErrMsg(ErrMsg, std::string("Couldn't execute program '") +
- path.toString() + "'");
- return;
- }
-
- // Make sure these get closed no matter what.
- AutoHandle hProcess(pi.hProcess);
- AutoHandle hThread(pi.hThread);
-
- // Assign the process to a job if a memory limit is defined.
- AutoHandle hJob(0);
- if (memoryLimit != 0) {
- hJob = CreateJobObject(0, 0);
- bool success = false;
- if (hJob != 0) {
- JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli;
- memset(&jeli, 0, sizeof(jeli));
- jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_PROCESS_MEMORY;
- jeli.ProcessMemoryLimit = uintptr_t(memoryLimit) * 1048576;
- if (SetInformationJobObject(hJob, JobObjectExtendedLimitInformation,
- &jeli, sizeof(jeli))) {
- if (AssignProcessToJobObject(hJob, pi.hProcess))
- success = true;
- }
- }
- if (!success) {
- SetLastError(GetLastError());
- MakeErrMsg(ErrMsg, std::string("Unable to set memory limit"));
- TerminateProcess(pi.hProcess, 1);
- WaitForSingleObject(pi.hProcess, INFINITE);
- return;
- }
- }
-}
-
bool Program::ChangeStdinToBinary(){
int result = _setmode( _fileno(stdin), _O_BINARY );
return result == -1;
More information about the llvm-commits
mailing list