Commit 81fe80e8 authored by Peter Hutterer's avatar Peter Hutterer
Browse files

process: add state enum and GetState()



Add a set of basic states to Process to allow callers to keep track of which
state a process is in (as seen from the library). This simplifies code that
needs to happen on certain conditions only, e.g. log file cleanup is only
needed if the process was previously started.
Signed-off-by: Peter Hutterer's avatarPeter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: default avatarChase Douglas <chase.douglas@canonical.com>
parent 43bdab62
......@@ -64,6 +64,22 @@ namespace testing {
*/
class Process {
public:
/**
* Describes the state of a process as seen by this library. This state
* changes some behaviors inside the library, most notably:
* * A process in state ERROR or NONE will fail to Kill() or Terminate()
* * A process in state FINISHED_SUCCESS or FINISHED_FAILURE will always
* succeed to Kill() or Terminate()
*/
enum State {
ERROR, /**< An error has occured, state is now unknown */
NONE, /**< The process has not been started yet */
RUNNING, /**< The process has been started */
FINISHED_SUCCESS, /**< The process finished with an exit code of 0 */
FINISHED_FAILURE, /**< The process finished with a non-zero exit code */
TERMINATED, /**< The process was successfully terminated by this library */
};
/**
* Helper function to adjust the environment of the current process.
*
......@@ -183,6 +199,13 @@ class Process {
*/
pid_t Pid() const;
/**
* Return the state of the process.
*
* @return The current state of the process
*/
enum Process::State GetState();
private:
struct Private;
std::auto_ptr<Private> d_;
......
......@@ -42,10 +42,27 @@
struct xorg::testing::Process::Private {
pid_t pid;
enum State state;
};
xorg::testing::Process::Process() : d_(new Private) {
d_->pid = -1;
d_->state = NONE;
}
enum xorg::testing::Process::State xorg::testing::Process::GetState() {
if (d_->state == RUNNING) {
int status;
int pid = waitpid(Pid(), &status, WNOHANG);
if (pid == Pid()) {
if (WIFEXITED(status)) {
d_->pid = -1;
d_->state = WEXITSTATUS(status) ? FINISHED_FAILURE : FINISHED_SUCCESS;
}
}
}
return d_->state;
}
void xorg::testing::Process::Start(const std::string &program, const std::vector<std::string> &argv) {
......@@ -55,6 +72,7 @@ void xorg::testing::Process::Start(const std::string &program, const std::vector
d_->pid = fork();
if (d_->pid == -1) {
d_->state = ERROR;
throw std::runtime_error("Failed to fork child process");
} else if (d_->pid == 0) { /* Child */
close(0);
......@@ -74,8 +92,11 @@ void xorg::testing::Process::Start(const std::string &program, const std::vector
execvp(program.c_str(), &args[0]);
d_->state = ERROR;
throw std::runtime_error("Failed to start process");
}
d_->state = RUNNING;
}
void xorg::testing::Process::Start(const std::string& program, va_list args) {
......@@ -117,6 +138,19 @@ bool xorg::testing::Process::WaitForExit(unsigned int timeout) {
bool xorg::testing::Process::KillSelf(int signal, unsigned int timeout) {
bool wait_success = true;
enum State state = GetState();
switch (state) {
case FINISHED_SUCCESS:
case FINISHED_FAILURE:
case TERMINATED:
return true;
case ERROR:
case NONE:
return false;
default:
break;
}
if (d_->pid == -1) {
return false;
} else if (d_->pid == 0) {
......@@ -125,12 +159,14 @@ bool xorg::testing::Process::KillSelf(int signal, unsigned int timeout) {
} else { /* Parent */
if (kill(d_->pid, signal) < 0) {
d_->pid = -1;
d_->state = ERROR;
return false;
}
if (timeout > 0)
wait_success = WaitForExit(timeout);
d_->pid = -1;
}
d_->state = TERMINATED;
return wait_success;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment