[PATCH xorg-gtest v3 07/11] process: add state enum and GetState()

Peter Hutterer peter.hutterer at who-t.net
Wed Aug 15 23:36:40 PDT 2012


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 <peter.hutterer at who-t.net>
---
Changes to v2:
- add two more starts for when the server has finsied on its own

 include/xorg/gtest/xorg-gtest-process.h | 23 +++++++++++++++++++++
 src/process.cpp                         | 36 +++++++++++++++++++++++++++++++++
 2 files changed, 59 insertions(+)

diff --git a/include/xorg/gtest/xorg-gtest-process.h b/include/xorg/gtest/xorg-gtest-process.h
index b4ac0d9..f1fc0ec 100644
--- a/include/xorg/gtest/xorg-gtest-process.h
+++ b/include/xorg/gtest/xorg-gtest-process.h
@@ -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_;
diff --git a/src/process.cpp b/src/process.cpp
index b85170b..4e903d6 100644
--- a/src/process.cpp
+++ b/src/process.cpp
@@ -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;
 }
 
-- 
1.7.11.2



More information about the xorg-devel mailing list