mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-19 03:24:09 +00:00
Add non-blocking Wait() for launched processes
- New ProcessInfo class to encapsulate information about child processes. - Generalized the Wait() to support non-blocking wait on child processes. - ExecuteNoWait() now returns a ProcessInfo object with information about the launched child. Users will be able to use this object to perform non-blocking wait. - ExecuteNoWait() now accepts an ExecutionFailed param that tells if execution failed or not. These changes will allow users to implement basic process parallel tools. Differential Revision: http://llvm-reviews.chandlerc.com/D1728 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@191763 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -21,6 +21,20 @@
|
||||
extern char **environ;
|
||||
#endif
|
||||
|
||||
#if defined(LLVM_ON_UNIX)
|
||||
#include <unistd.h>
|
||||
void sleep_for(unsigned int seconds) {
|
||||
sleep(seconds);
|
||||
}
|
||||
#elif defined(LLVM_ON_WIN32)
|
||||
#include <windows.h>
|
||||
void sleep_for(unsigned int seconds) {
|
||||
Sleep(seconds * 1000);
|
||||
}
|
||||
#else
|
||||
#error sleep_for is not implemented on your platform.
|
||||
#endif
|
||||
|
||||
// From TestMain.cpp.
|
||||
extern const char *TestMainArgv0;
|
||||
|
||||
@ -88,4 +102,93 @@ TEST(ProgramTest, CreateProcessTrailingSlash) {
|
||||
EXPECT_EQ(0, rc);
|
||||
}
|
||||
|
||||
TEST(ProgramTest, TestExecuteNoWait) {
|
||||
using namespace llvm::sys;
|
||||
|
||||
if (getenv("LLVM_PROGRAM_TEST_EXECUTE_NO_WAIT")) {
|
||||
sleep_for(/*seconds*/ 1);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
std::string Executable =
|
||||
sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1);
|
||||
const char *argv[] = {
|
||||
Executable.c_str(),
|
||||
"--gtest_filter=ProgramTest.TestExecuteNoWait",
|
||||
0
|
||||
};
|
||||
|
||||
// Add LLVM_PROGRAM_TEST_EXECUTE_NO_WAIT to the environment of the child.
|
||||
std::vector<const char *> envp;
|
||||
CopyEnvironment(envp);
|
||||
envp.push_back("LLVM_PROGRAM_TEST_EXECUTE_NO_WAIT=1");
|
||||
envp.push_back(0);
|
||||
|
||||
std::string Error;
|
||||
bool ExecutionFailed;
|
||||
ProcessInfo PI1 =
|
||||
ExecuteNoWait(Executable, argv, &envp[0], 0, 0, &Error, &ExecutionFailed);
|
||||
ASSERT_FALSE(ExecutionFailed) << Error;
|
||||
ASSERT_NE(PI1.Pid, 0) << "Invalid process id";
|
||||
|
||||
unsigned LoopCount = 0;
|
||||
|
||||
// Test that Wait() with WaitUntilTerminates=true works. In this case,
|
||||
// LoopCount should only be incremented once.
|
||||
while (true) {
|
||||
++LoopCount;
|
||||
ProcessInfo WaitResult = Wait(PI1, 0, true, &Error);
|
||||
ASSERT_TRUE(Error.empty());
|
||||
if (WaitResult.Pid == PI1.Pid)
|
||||
break;
|
||||
}
|
||||
|
||||
EXPECT_EQ(LoopCount, 1u) << "LoopCount should be 1";
|
||||
|
||||
ProcessInfo PI2 =
|
||||
ExecuteNoWait(Executable, argv, &envp[0], 0, 0, &Error, &ExecutionFailed);
|
||||
ASSERT_FALSE(ExecutionFailed) << Error;
|
||||
ASSERT_NE(PI2.Pid, 0) << "Invalid process id";
|
||||
|
||||
// Test that Wait() with SecondsToWait=0 performs a non-blocking wait. In this
|
||||
// cse, LoopCount should be greater than 1 (more than one increment occurs).
|
||||
while (true) {
|
||||
++LoopCount;
|
||||
ProcessInfo WaitResult = Wait(PI2, 0, false, &Error);
|
||||
ASSERT_TRUE(Error.empty());
|
||||
if (WaitResult.Pid == PI2.Pid)
|
||||
break;
|
||||
}
|
||||
|
||||
ASSERT_GT(LoopCount, 1u) << "LoopCount should be >1";
|
||||
}
|
||||
|
||||
TEST(ProgramTest, TestExecuteNegative) {
|
||||
std::string Executable = "i_dont_exist";
|
||||
const char *argv[] = { Executable.c_str(), 0 };
|
||||
|
||||
{
|
||||
std::string Error;
|
||||
bool ExecutionFailed;
|
||||
int RetCode =
|
||||
ExecuteAndWait(Executable, argv, 0, 0, 0, 0, &Error, &ExecutionFailed);
|
||||
ASSERT_TRUE(RetCode < 0) << "On error ExecuteAndWait should return 0 or "
|
||||
"positive value indicating the result code";
|
||||
ASSERT_TRUE(ExecutionFailed);
|
||||
ASSERT_FALSE(Error.empty());
|
||||
}
|
||||
|
||||
{
|
||||
std::string Error;
|
||||
bool ExecutionFailed;
|
||||
ProcessInfo PI =
|
||||
ExecuteNoWait(Executable, argv, 0, 0, 0, &Error, &ExecutionFailed);
|
||||
ASSERT_EQ(PI.Pid, 0)
|
||||
<< "On error ExecuteNoWait should return an invalid ProcessInfo";
|
||||
ASSERT_TRUE(ExecutionFailed);
|
||||
ASSERT_FALSE(Error.empty());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
Reference in New Issue
Block a user