Remove duplication in Program::Execute{And,No}Wait.

Implemented by moving the code out of static functions into methods of Program
class.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@76340 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Mikhail Glushenkov
2009-07-18 21:43:12 +00:00
parent 617dd7baa6
commit 3140619c63
4 changed files with 194 additions and 368 deletions

View File

@ -142,49 +142,47 @@ static void SetMemoryLimits (unsigned size)
#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 @@ Program::ExecuteAndWait(const Path& path,
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 @@ Program::ExecuteAndWait(const Path& path,
// 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 @@ Program::ExecuteAndWait(const Path& path,
}
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;