diff options
author | Kyle Edwards <kyle.edwards@kitware.com> | 2023-07-26 20:58:34 (GMT) |
---|---|---|
committer | Kyle Edwards <kyle.edwards@kitware.com> | 2023-08-29 14:51:30 (GMT) |
commit | 96b3dd329ecdecdf2110cab4bc368690a630e012 (patch) | |
tree | 31cb0510192cfce573a400b517299b56c6db6476 /Source/CTest | |
parent | b15ad7ebb6b96630396fb54b4679075a52c5f79b (diff) | |
download | CMake-96b3dd329ecdecdf2110cab4bc368690a630e012.zip CMake-96b3dd329ecdecdf2110cab4bc368690a630e012.tar.gz CMake-96b3dd329ecdecdf2110cab4bc368690a630e012.tar.bz2 |
cmCTestLaunchReporter: Replace cmsysProcess with cmUVProcessChain
And convert cmCTestLaunch and cmCTestBuildHandler too.
Diffstat (limited to 'Source/CTest')
-rw-r--r-- | Source/CTest/cmCTestBuildHandler.cxx | 291 | ||||
-rw-r--r-- | Source/CTest/cmCTestBuildHandler.h | 6 | ||||
-rw-r--r-- | Source/CTest/cmCTestLaunch.cxx | 126 | ||||
-rw-r--r-- | Source/CTest/cmCTestLaunch.h | 5 | ||||
-rw-r--r-- | Source/CTest/cmCTestLaunchReporter.cxx | 50 | ||||
-rw-r--r-- | Source/CTest/cmCTestLaunchReporter.h | 4 |
6 files changed, 256 insertions, 226 deletions
diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx index 00ecf42..859798e 100644 --- a/Source/CTest/cmCTestBuildHandler.cxx +++ b/Source/CTest/cmCTestBuildHandler.cxx @@ -3,15 +3,17 @@ #include "cmCTestBuildHandler.h" #include <cstdlib> +#include <memory> #include <ratio> #include <set> #include <utility> #include <cmext/algorithm> +#include <cm3p/uv.h> + #include "cmsys/Directory.hxx" #include "cmsys/FStream.hxx" -#include "cmsys/Process.h" #include "cmCTest.h" #include "cmCTestLaunchReporter.h" @@ -24,6 +26,9 @@ #include "cmStringAlgorithms.h" #include "cmStringReplaceHelper.h" #include "cmSystemTools.h" +#include "cmUVHandlePtr.h" +#include "cmUVProcessChain.h" +#include "cmUVStream.h" #include "cmValue.h" #include "cmXMLWriter.h" @@ -420,7 +425,7 @@ int cmCTestBuildHandler::ProcessHandler() cmStringReplaceHelper colorRemover("\x1b\\[[0-9;]*m", "", nullptr); this->ColorRemover = &colorRemover; int retVal = 0; - int res = cmsysProcess_State_Exited; + bool res = true; if (!this->CTest->GetShowOnly()) { res = this->RunMakeCommand(makeCommand, &retVal, buildDirectory.c_str(), 0, ofs); @@ -475,7 +480,7 @@ int cmCTestBuildHandler::ProcessHandler() } this->GenerateXMLFooter(xml, elapsed_build_time); - if (res != cmsysProcess_State_Exited || retVal || this->TotalErrors > 0) { + if (!res || retVal || this->TotalErrors > 0) { cmCTestLog(this->CTest, ERROR_MESSAGE, "Error(s) when building project" << std::endl); } @@ -764,10 +769,10 @@ void cmCTestBuildHandler::LaunchHelper::WriteScrapeMatchers( } } -int cmCTestBuildHandler::RunMakeCommand(const std::string& command, - int* retVal, const char* dir, - int timeout, std::ostream& ofs, - Encoding encoding) +bool cmCTestBuildHandler::RunMakeCommand(const std::string& command, + int* retVal, const char* dir, + int timeout, std::ostream& ofs, + Encoding encoding) { // First generate the command and arguments std::vector<std::string> args = cmSystemTools::ParseArguments(command); @@ -776,19 +781,9 @@ int cmCTestBuildHandler::RunMakeCommand(const std::string& command, return false; } - std::vector<const char*> argv; - argv.reserve(args.size() + 1); - for (std::string const& arg : args) { - argv.push_back(arg.c_str()); - } - argv.push_back(nullptr); - cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Run command:", this->Quiet); - for (char const* arg : argv) { - if (!arg) { - break; - } + for (auto const& arg : args) { cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " \"" << arg << "\"", this->Quiet); } @@ -800,21 +795,20 @@ int cmCTestBuildHandler::RunMakeCommand(const std::string& command, static_cast<void>(launchHelper); // Now create process object - cmsysProcess* cp = cmsysProcess_New(); - cmsysProcess_SetCommand(cp, argv.data()); - cmsysProcess_SetWorkingDirectory(cp, dir); - cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1); - cmsysProcess_SetTimeout(cp, timeout); - cmsysProcess_Execute(cp); + cmUVProcessChainBuilder builder; + builder.AddCommand(args) + .SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT) + .SetBuiltinStream(cmUVProcessChainBuilder::Stream_ERROR); + if (dir) { + builder.SetWorkingDirectory(dir); + } + auto chain = builder.Start(); // Initialize tick's std::string::size_type tick = 0; - const std::string::size_type tick_len = 1024; + static constexpr std::string::size_type tick_len = 1024; - char* data; - int length; cmProcessOutput processOutput(encoding); - std::string strdata; cmCTestOptionalLog( this->CTest, HANDLER_PROGRESS_OUTPUT, " Each symbol represents " @@ -836,39 +830,65 @@ int cmCTestBuildHandler::RunMakeCommand(const std::string& command, this->WarningQuotaReached = false; this->ErrorQuotaReached = false; + cm::uv_timer_ptr timer; + bool timedOut = false; + timer.init(chain.GetLoop(), &timedOut); + if (timeout > 0) { + timer.start( + [](uv_timer_t* t) { + auto* timedOutPtr = static_cast<bool*>(t->data); + *timedOutPtr = true; + }, + timeout * 1000, 0); + } + // For every chunk of data - int res; - while ((res = cmsysProcess_WaitForData(cp, &data, &length, nullptr))) { - // Replace '\0' with '\n', since '\0' does not really make sense. This is - // for Visual Studio output - for (int cc = 0; cc < length; ++cc) { - if (data[cc] == 0) { - data[cc] = '\n'; - } - } + cm::uv_pipe_ptr outputStream; + bool outFinished = false; + cm::uv_pipe_ptr errorStream; + bool errFinished = false; + auto startRead = [this, &chain, &processOutput, &tick, + &ofs](cm::uv_pipe_ptr& pipe, int stream, + t_BuildProcessingQueueType& queue, bool& finished, + int id) -> std::unique_ptr<cmUVStreamReadHandle> { + pipe.init(chain.GetLoop(), 0); + uv_pipe_open(pipe, stream); + return cmUVStreamRead( + pipe, + [this, &processOutput, &queue, id, &tick, &ofs](std::vector<char> data) { + // Replace '\0' with '\n', since '\0' does not really make sense. This + // is for Visual Studio output + for (auto& c : data) { + if (c == 0) { + c = '\n'; + } + } - // Process the chunk of data - if (res == cmsysProcess_Pipe_STDERR) { - processOutput.DecodeText(data, length, strdata, 1); - this->ProcessBuffer(strdata.c_str(), strdata.size(), tick, tick_len, ofs, - &this->BuildProcessingErrorQueue); - } else { - processOutput.DecodeText(data, length, strdata, 2); - this->ProcessBuffer(strdata.c_str(), strdata.size(), tick, tick_len, ofs, - &this->BuildProcessingQueue); - } - } - processOutput.DecodeText(std::string(), strdata, 1); - if (!strdata.empty()) { - this->ProcessBuffer(strdata.c_str(), strdata.size(), tick, tick_len, ofs, - &this->BuildProcessingErrorQueue); - } - processOutput.DecodeText(std::string(), strdata, 2); - if (!strdata.empty()) { - this->ProcessBuffer(strdata.c_str(), strdata.size(), tick, tick_len, ofs, - &this->BuildProcessingQueue); + // Process the chunk of data + std::string strdata; + processOutput.DecodeText(data.data(), data.size(), strdata, id); + this->ProcessBuffer(strdata.c_str(), strdata.size(), tick, tick_len, + ofs, &queue); + }, + [this, &processOutput, &queue, id, &tick, &ofs, &finished]() { + std::string strdata; + processOutput.DecodeText(std::string(), strdata, id); + if (!strdata.empty()) { + this->ProcessBuffer(strdata.c_str(), strdata.size(), tick, tick_len, + ofs, &queue); + } + finished = true; + }); + }; + auto outputHandle = startRead(outputStream, chain.OutputStream(), + this->BuildProcessingQueue, outFinished, 1); + auto errorHandle = + startRead(errorStream, chain.ErrorStream(), + this->BuildProcessingErrorQueue, errFinished, 2); + + while (!timedOut && !(outFinished && errFinished && chain.Finished())) { + uv_run(&chain.GetLoop(), UV_RUN_ONCE); } - this->ProcessBuffer(nullptr, 0, tick, tick_len, ofs, &this->BuildProcessingQueue); this->ProcessBuffer(nullptr, 0, tick, tick_len, ofs, @@ -879,90 +899,93 @@ int cmCTestBuildHandler::RunMakeCommand(const std::string& command, << std::endl, this->Quiet); - // Properly handle output of the build command - cmsysProcess_WaitForExit(cp, nullptr); - int result = cmsysProcess_GetState(cp); - - if (result == cmsysProcess_State_Exited) { - if (retVal) { - *retVal = cmsysProcess_GetExitValue(cp); - cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, - "Command exited with the value: " << *retVal - << std::endl, - this->Quiet); - // if a non zero return value - if (*retVal) { - // If there was an error running command, report that on the - // dashboard. - if (this->UseCTestLaunch) { - // For launchers, do not record this top-level error if other - // more granular build errors have already been captured. - bool launcherXMLFound = false; - cmsys::Directory launchDir; - launchDir.Load(this->CTestLaunchDir); - unsigned long n = launchDir.GetNumberOfFiles(); - for (unsigned long i = 0; i < n; ++i) { - const char* fname = launchDir.GetFile(i); - if (cmHasLiteralSuffix(fname, ".xml")) { - launcherXMLFound = true; - break; + if (chain.Finished()) { + auto const& status = chain.GetStatus(0); + auto exception = status.GetException(); + switch (exception.first) { + case cmUVProcessChain::ExceptionCode::None: + if (retVal) { + *retVal = static_cast<int>(status.ExitStatus); + cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + "Command exited with the value: " << *retVal + << std::endl, + this->Quiet); + // if a non zero return value + if (*retVal) { + // If there was an error running command, report that on the + // dashboard. + if (this->UseCTestLaunch) { + // For launchers, do not record this top-level error if other + // more granular build errors have already been captured. + bool launcherXMLFound = false; + cmsys::Directory launchDir; + launchDir.Load(this->CTestLaunchDir); + unsigned long n = launchDir.GetNumberOfFiles(); + for (unsigned long i = 0; i < n; ++i) { + const char* fname = launchDir.GetFile(i); + if (cmHasLiteralSuffix(fname, ".xml")) { + launcherXMLFound = true; + break; + } + } + if (!launcherXMLFound) { + cmCTestLaunchReporter reporter; + reporter.RealArgs = args; + reporter.ComputeFileNames(); + reporter.ExitCode = *retVal; + reporter.Status = status; + // Use temporary BuildLog file to populate this error for + // CDash. + ofs.flush(); + reporter.LogOut = this->LogFileNames["Build"]; + reporter.LogOut += ".tmp"; + reporter.WriteXML(); + } + } else { + cmCTestBuildErrorWarning errorwarning; + errorwarning.LineNumber = 0; + errorwarning.LogLine = 1; + errorwarning.Text = cmStrCat( + "*** WARNING non-zero return value in ctest from: ", args[0]); + errorwarning.PreContext.clear(); + errorwarning.PostContext.clear(); + errorwarning.Error = false; + this->ErrorsAndWarnings.push_back(std::move(errorwarning)); + this->TotalWarnings++; } } - if (!launcherXMLFound) { - cmCTestLaunchReporter reporter; - reporter.RealArgs = args; - reporter.ComputeFileNames(); - reporter.ExitCode = *retVal; - reporter.Process = cp; - // Use temporary BuildLog file to populate this error for CDash. - ofs.flush(); - reporter.LogOut = this->LogFileNames["Build"]; - reporter.LogOut += ".tmp"; - reporter.WriteXML(); - } - } else { - cmCTestBuildErrorWarning errorwarning; - errorwarning.LineNumber = 0; - errorwarning.LogLine = 1; - errorwarning.Text = cmStrCat( - "*** WARNING non-zero return value in ctest from: ", argv[0]); - errorwarning.PreContext.clear(); - errorwarning.PostContext.clear(); - errorwarning.Error = false; - this->ErrorsAndWarnings.push_back(std::move(errorwarning)); - this->TotalWarnings++; } - } - } - } else if (result == cmsysProcess_State_Exception) { - if (retVal) { - *retVal = cmsysProcess_GetExitException(cp); - cmCTestOptionalLog(this->CTest, WARNING, - "There was an exception: " << *retVal << std::endl, - this->Quiet); + break; + case cmUVProcessChain::ExceptionCode::Spawn: { + // If there was an error running command, report that on the dashboard. + cmCTestBuildErrorWarning errorwarning; + errorwarning.LineNumber = 0; + errorwarning.LogLine = 1; + errorwarning.Text = + cmStrCat("*** ERROR executing: ", exception.second); + errorwarning.PreContext.clear(); + errorwarning.PostContext.clear(); + errorwarning.Error = true; + this->ErrorsAndWarnings.push_back(std::move(errorwarning)); + this->TotalErrors++; + cmCTestLog(this->CTest, ERROR_MESSAGE, + "There was an error: " << exception.second << std::endl); + } break; + default: + if (retVal) { + *retVal = status.TermSignal; + cmCTestOptionalLog( + this->CTest, WARNING, + "There was an exception: " << *retVal << std::endl, this->Quiet); + } + break; } - } else if (result == cmsysProcess_State_Expired) { + } else { cmCTestOptionalLog(this->CTest, WARNING, "There was a timeout" << std::endl, this->Quiet); - } else if (result == cmsysProcess_State_Error) { - // If there was an error running command, report that on the dashboard. - cmCTestBuildErrorWarning errorwarning; - errorwarning.LineNumber = 0; - errorwarning.LogLine = 1; - errorwarning.Text = - cmStrCat("*** ERROR executing: ", cmsysProcess_GetErrorString(cp)); - errorwarning.PreContext.clear(); - errorwarning.PostContext.clear(); - errorwarning.Error = true; - this->ErrorsAndWarnings.push_back(std::move(errorwarning)); - this->TotalErrors++; - cmCTestLog(this->CTest, ERROR_MESSAGE, - "There was an error: " << cmsysProcess_GetErrorString(cp) - << std::endl); } - cmsysProcess_Delete(cp); - return result; + return true; } // ###################################################################### diff --git a/Source/CTest/cmCTestBuildHandler.h b/Source/CTest/cmCTestBuildHandler.h index e33294d..90945b1 100644 --- a/Source/CTest/cmCTestBuildHandler.h +++ b/Source/CTest/cmCTestBuildHandler.h @@ -53,9 +53,9 @@ private: //! Run command specialized for make and configure. Returns process status // and retVal is return value or exception. - int RunMakeCommand(const std::string& command, int* retVal, const char* dir, - int timeout, std::ostream& ofs, - Encoding encoding = cmProcessOutput::Auto); + bool RunMakeCommand(const std::string& command, int* retVal, const char* dir, + int timeout, std::ostream& ofs, + Encoding encoding = cmProcessOutput::Auto); enum { diff --git a/Source/CTest/cmCTestLaunch.cxx b/Source/CTest/cmCTestLaunch.cxx index 4a33869..6b13ad1 100644 --- a/Source/CTest/cmCTestLaunch.cxx +++ b/Source/CTest/cmCTestLaunch.cxx @@ -2,13 +2,19 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCTestLaunch.h" +#include <cstdio> #include <cstring> #include <iostream> +#include <memory> +#include <utility> + +#include <cm3p/uv.h> #include "cmsys/FStream.hxx" -#include "cmsys/Process.h" #include "cmsys/RegularExpression.hxx" +#include "cm_fileno.hxx" + #include "cmCTestLaunchReporter.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" @@ -17,6 +23,9 @@ #include "cmStateSnapshot.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmUVHandlePtr.h" +#include "cmUVProcessChain.h" +#include "cmUVStream.h" #include "cmake.h" #ifdef _WIN32 @@ -28,8 +37,6 @@ cmCTestLaunch::cmCTestLaunch(int argc, const char* const* argv) { - this->Process = nullptr; - if (!this->ParseArguments(argc, argv)) { return; } @@ -40,13 +47,9 @@ cmCTestLaunch::cmCTestLaunch(int argc, const char* const* argv) this->ScrapeRulesLoaded = false; this->HaveOut = false; this->HaveErr = false; - this->Process = cmsysProcess_New(); } -cmCTestLaunch::~cmCTestLaunch() -{ - cmsysProcess_Delete(this->Process); -} +cmCTestLaunch::~cmCTestLaunch() = default; bool cmCTestLaunch::ParseArguments(int argc, const char* const* argv) { @@ -113,15 +116,12 @@ bool cmCTestLaunch::ParseArguments(int argc, const char* const* argv) // Extract the real command line. if (arg0) { - this->RealArgC = argc - arg0; - this->RealArgV = argv + arg0; - for (int i = 0; i < this->RealArgC; ++i) { - this->HandleRealArg(this->RealArgV[i]); + for (int i = 0; i < argc - arg0; ++i) { + this->RealArgV.emplace_back((argv + arg0)[i]); + this->HandleRealArg((argv + arg0)[i]); } return true; } - this->RealArgC = 0; - this->RealArgV = nullptr; std::cerr << "No launch/command separator ('--') found!\n"; return false; } @@ -151,17 +151,22 @@ void cmCTestLaunch::RunChild() } // Prepare to run the real command. - cmsysProcess* cp = this->Process; - cmsysProcess_SetCommand(cp, this->RealArgV); + cmUVProcessChainBuilder builder; + builder.AddCommand(this->RealArgV); cmsys::ofstream fout; cmsys::ofstream ferr; if (this->Reporter.Passthru) { // In passthru mode we just share the output pipes. - cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDOUT, 1); - cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDERR, 1); + builder + .SetExternalStream(cmUVProcessChainBuilder::Stream_OUTPUT, + cm_fileno(stdout)) + .SetExternalStream(cmUVProcessChainBuilder::Stream_ERROR, + cm_fileno(stderr)); } else { // In full mode we record the child output pipes to log files. + builder.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT) + .SetBuiltinStream(cmUVProcessChainBuilder::Stream_ERROR); fout.open(this->Reporter.LogOut.c_str(), std::ios::out | std::ios::binary); ferr.open(this->Reporter.LogErr.c_str(), std::ios::out | std::ios::binary); } @@ -174,51 +179,65 @@ void cmCTestLaunch::RunChild() #endif // Run the real command. - cmsysProcess_Execute(cp); + auto chain = builder.Start(); // Record child stdout and stderr if necessary. + cm::uv_pipe_ptr outPipe; + cm::uv_pipe_ptr errPipe; + bool outFinished = true; + bool errFinished = true; + cmProcessOutput processOutput; + std::unique_ptr<cmUVStreamReadHandle> outputHandle; + std::unique_ptr<cmUVStreamReadHandle> errorHandle; if (!this->Reporter.Passthru) { - char* data = nullptr; - int length = 0; - cmProcessOutput processOutput; - std::string strdata; - while (int p = cmsysProcess_WaitForData(cp, &data, &length, nullptr)) { - if (p == cmsysProcess_Pipe_STDOUT) { - processOutput.DecodeText(data, length, strdata, 1); - fout.write(strdata.c_str(), strdata.size()); - std::cout.write(strdata.c_str(), strdata.size()); - this->HaveOut = true; - } else if (p == cmsysProcess_Pipe_STDERR) { - processOutput.DecodeText(data, length, strdata, 2); - ferr.write(strdata.c_str(), strdata.size()); - std::cerr.write(strdata.c_str(), strdata.size()); - this->HaveErr = true; - } - } - processOutput.DecodeText(std::string(), strdata, 1); - if (!strdata.empty()) { - fout.write(strdata.c_str(), strdata.size()); - std::cout.write(strdata.c_str(), strdata.size()); - } - processOutput.DecodeText(std::string(), strdata, 2); - if (!strdata.empty()) { - ferr.write(strdata.c_str(), strdata.size()); - std::cerr.write(strdata.c_str(), strdata.size()); - } + auto beginRead = [&chain, &processOutput]( + cm::uv_pipe_ptr& pipe, int stream, std::ostream& out, + cmsys::ofstream& file, bool& haveData, bool& finished, + int id) -> std::unique_ptr<cmUVStreamReadHandle> { + pipe.init(chain.GetLoop(), 0); + uv_pipe_open(pipe, stream); + finished = false; + return cmUVStreamRead( + pipe, + [&processOutput, &out, &file, id, &haveData](std::vector<char> data) { + std::string strdata; + processOutput.DecodeText(data.data(), data.size(), strdata, id); + file.write(strdata.c_str(), strdata.size()); + out.write(strdata.c_str(), strdata.size()); + haveData = true; + }, + [&processOutput, &out, &file, &finished, id]() { + std::string strdata; + processOutput.DecodeText(std::string(), strdata, id); + if (!strdata.empty()) { + file.write(strdata.c_str(), strdata.size()); + out.write(strdata.c_str(), strdata.size()); + } + finished = true; + }); + }; + outputHandle = beginRead(outPipe, chain.OutputStream(), std::cout, fout, + this->HaveOut, outFinished, 1); + errorHandle = beginRead(errPipe, chain.ErrorStream(), std::cerr, ferr, + this->HaveErr, errFinished, 2); } // Wait for the real command to finish. - cmsysProcess_WaitForExit(cp, nullptr); - this->Reporter.ExitCode = cmsysProcess_GetExitValue(cp); + while (!(chain.Finished() && outFinished && errFinished)) { + uv_run(&chain.GetLoop(), UV_RUN_ONCE); + } + this->Reporter.Status = chain.GetStatus(0); + if (this->Reporter.Status.GetException().first == + cmUVProcessChain::ExceptionCode::Spawn) { + this->Reporter.ExitCode = 1; + } else { + this->Reporter.ExitCode = + static_cast<int>(this->Reporter.Status.ExitStatus); + } } int cmCTestLaunch::Run() { - if (!this->Process) { - std::cerr << "Could not allocate cmsysProcess instance!\n"; - return -1; - } - this->RunChild(); if (this->CheckResults()) { @@ -226,7 +245,6 @@ int cmCTestLaunch::Run() } this->LoadConfig(); - this->Reporter.Process = this->Process; this->Reporter.WriteXML(); return this->Reporter.ExitCode; diff --git a/Source/CTest/cmCTestLaunch.h b/Source/CTest/cmCTestLaunch.h index c5a6476..ef21a26 100644 --- a/Source/CTest/cmCTestLaunch.h +++ b/Source/CTest/cmCTestLaunch.h @@ -43,15 +43,12 @@ private: bool ParseArguments(int argc, const char* const* argv); // The real command line appearing after launcher arguments. - int RealArgC; - const char* const* RealArgV; + std::vector<std::string> RealArgV; // The real command line after response file expansion. std::vector<std::string> RealArgs; void HandleRealArg(const char* arg); - struct cmsysProcess_s* Process; - // Whether or not any data have been written to stdout or stderr. bool HaveOut; bool HaveErr; diff --git a/Source/CTest/cmCTestLaunchReporter.cxx b/Source/CTest/cmCTestLaunchReporter.cxx index 149ba5d..4b4e5c5 100644 --- a/Source/CTest/cmCTestLaunchReporter.cxx +++ b/Source/CTest/cmCTestLaunchReporter.cxx @@ -2,8 +2,9 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCTestLaunchReporter.h" +#include <utility> + #include "cmsys/FStream.hxx" -#include "cmsys/Process.h" #include "cmsys/RegularExpression.hxx" #include "cmCryptoHash.h" @@ -22,6 +23,7 @@ cmCTestLaunchReporter::cmCTestLaunchReporter() { this->Passthru = true; + this->Status.Finished = true; this->ExitCode = 1; this->CWD = cmSystemTools::GetCurrentWorkingDirectory(); @@ -231,35 +233,23 @@ void cmCTestLaunchReporter::WriteXMLResult(cmXMLElement& e2) // ExitCondition cmXMLElement e4(e3, "ExitCondition"); - cmsysProcess* cp = this->Process; - switch (cmsysProcess_GetState(cp)) { - case cmsysProcess_State_Starting: - e4.Content("No process has been executed"); - break; - case cmsysProcess_State_Executing: - e4.Content("The process is still executing"); - break; - case cmsysProcess_State_Disowned: - e4.Content("Disowned"); - break; - case cmsysProcess_State_Killed: - e4.Content("Killed by parent"); - break; - - case cmsysProcess_State_Expired: - e4.Content("Killed when timeout expired"); - break; - case cmsysProcess_State_Exited: - e4.Content(this->ExitCode); - break; - case cmsysProcess_State_Exception: - e4.Content("Terminated abnormally: "); - e4.Content(cmsysProcess_GetExceptionString(cp)); - break; - case cmsysProcess_State_Error: - e4.Content("Error administrating child process: "); - e4.Content(cmsysProcess_GetErrorString(cp)); - break; + if (this->Status.Finished) { + auto exception = this->Status.GetException(); + switch (exception.first) { + case cmUVProcessChain::ExceptionCode::None: + e4.Content(this->ExitCode); + break; + case cmUVProcessChain::ExceptionCode::Spawn: + e4.Content("Error administrating child process: "); + e4.Content(exception.second); + break; + default: + e4.Content("Terminated abnormally: "); + e4.Content(exception.second); + break; + } + } else { + e4.Content("Killed when timeout expired"); } } diff --git a/Source/CTest/cmCTestLaunchReporter.h b/Source/CTest/cmCTestLaunchReporter.h index 4be0d9b..2bb78f8 100644 --- a/Source/CTest/cmCTestLaunchReporter.h +++ b/Source/CTest/cmCTestLaunchReporter.h @@ -10,6 +10,8 @@ #include "cmsys/RegularExpression.hxx" +#include "cmUVProcessChain.h" + class cmXMLElement; /** \class cmCTestLaunchReporter @@ -48,7 +50,7 @@ public: void ComputeFileNames(); bool Passthru; - struct cmsysProcess_s* Process; + cmUVProcessChain::Status Status; int ExitCode; // Temporary log files for stdout and stderr of real command. |