Browse Source

BUG: Fixed issue where ctest would hang if a process terminated with output in its buffers but no newline

Zach Mullen 16 years ago
parent
commit
a02ef56401
3 changed files with 39 additions and 12 deletions
  1. 8 3
      Source/CTest/cmCTestRunTest.cxx
  2. 28 6
      Source/CTest/cmProcess.cxx
  3. 3 3
      Source/CTest/cmProcess.h

+ 8 - 3
Source/CTest/cmCTestRunTest.cxx

@@ -38,18 +38,19 @@ bool cmCTestRunTest::IsRunning()
 void cmCTestRunTest::CheckOutput()
 {
   std::string out, err;
-  this->TestProcess->CheckOutput(.1);
+  bool running = this->TestProcess->CheckOutput(.1);
   //start our timeout for reading the process output
   double clock_start = cmSystemTools::GetTime();
   int pipe;
   bool gotStdOut = false;
   bool gotStdErr = false;
   while((pipe = this->TestProcess->
-        GetNextOutputLine(out, err, gotStdOut, gotStdErr) )
+        GetNextOutputLine(out, err, gotStdOut, gotStdErr, running) )
         != cmsysProcess_Pipe_Timeout)
     {
     if(pipe == cmsysProcess_Pipe_STDOUT ||
-       pipe == cmsysProcess_Pipe_STDERR)
+       pipe == cmsysProcess_Pipe_STDERR ||
+       pipe == cmsysProcess_Pipe_None)
       {
       if(gotStdErr)
         {
@@ -65,6 +66,10 @@ void cmCTestRunTest::CheckOutput()
         this->ProcessOutput += out;
         this->ProcessOutput += "\n";
         }
+      if(pipe == cmsysProcess_Pipe_None)
+        {
+        break;
+        }
       }
     gotStdOut = false;
     gotStdErr = false;

+ 28 - 6
Source/CTest/cmProcess.cxx

@@ -77,7 +77,8 @@ bool cmProcess::StartProcess()
 int cmProcess::GetNextOutputLine(std::string& stdOutLine,
                             std::string& stdErrLine,
                             bool& gotStdOut,
-                            bool& gotStdErr)
+                            bool& gotStdErr,
+                            bool running)
 {
   if(this->StdErrorBuffer.empty() && this->StdOutBuffer.empty())
     {
@@ -91,6 +92,27 @@ int cmProcess::GetNextOutputLine(std::string& stdOutLine,
     this->StdOutBuffer.begin();
   std::vector<char>::iterator erriter = 
     this->StdErrorBuffer.begin();
+
+  //If process terminated, flush the buffer
+  if(!running)
+    {
+    if(!this->StdErrorBuffer.empty())
+      {
+      gotStdErr = true;
+      stdErrLine.append(&this->StdErrorBuffer[0], this->StdErrorBuffer.size());
+      this->StdErrorBuffer.erase(this->StdErrorBuffer.begin(), 
+        this->StdErrorBuffer.end());
+      }
+    if(!this->StdOutBuffer.empty())
+      {
+      gotStdOut = true;
+      stdOutLine.append(&this->StdOutBuffer[0], this->StdOutBuffer.size());
+      this->StdOutBuffer.erase(this->StdOutBuffer.begin(),
+        this->StdOutBuffer.end());
+      }
+    return cmsysProcess_Pipe_None;
+    }
+
   // Check for a newline in stdout.
   for(;outiter != this->StdOutBuffer.end(); ++outiter)
     {
@@ -145,7 +167,7 @@ int cmProcess::GetNextOutputLine(std::string& stdOutLine,
 }
 // return true if there is a new line of data
 // return false if there is no new data
-void cmProcess::CheckOutput(double timeout)
+bool cmProcess::CheckOutput(double timeout)
 {
   // Wait for data from the process.
   int length;
@@ -159,7 +181,7 @@ void cmProcess::CheckOutput(double timeout)
       {
       // Timeout has been exceeded.
       this->LastOutputPipe = pipe;
-      return;
+      return true;
       }
     else if(pipe == cmsysProcess_Pipe_STDOUT)
       {
@@ -180,17 +202,17 @@ void cmProcess::CheckOutput(double timeout)
       if(!this->StdOutBuffer.empty())
         {
         this->LastOutputPipe = cmsysProcess_Pipe_STDOUT;
-        return;
+        return false;
         }
       else if(!this->StdErrorBuffer.empty())
         {
         this->LastOutputPipe = cmsysProcess_Pipe_STDERR;
-        return;
+        return false;
         }
       else
         {
         this->LastOutputPipe = cmsysProcess_Pipe_None;
-        return;
+        return false;
         }
       }
     }

+ 3 - 3
Source/CTest/cmProcess.h

@@ -40,8 +40,8 @@ public:
   // Return true if the process starts
   bool StartProcess();
   
-  // return process state
-  void CheckOutput(double timeout);
+  // return false if process has exited, true otherwise
+  bool CheckOutput(double timeout);
   // return the process status
   int GetProcessStatus();
   // return true if the process is running
@@ -53,7 +53,7 @@ public:
   int GetExitValue() { return this->ExitValue;}
   double GetTotalTime() { return this->TotalTime;}
   int GetNextOutputLine(std::string& stdOutLine, std::string& stdErrLine,
-                        bool& gotStdOut, bool& gotStdErr);
+                        bool& gotStdOut, bool& gotStdErr, bool running);
 private:
   int LastOutputPipe;
   double Timeout;