summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/CTest/cmCTestScriptHandler.cxx84
-rw-r--r--Source/cmSystemTools.cxx84
-rw-r--r--Source/cmSystemTools.h20
-rw-r--r--Tests/CMakeLib/testUVProcessChainHelper.cxx4
4 files changed, 123 insertions, 69 deletions
diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx
index 461ad1a..48f8f6d 100644
--- a/Source/CTest/cmCTestScriptHandler.cxx
+++ b/Source/CTest/cmCTestScriptHandler.cxx
@@ -11,8 +11,9 @@
#include <cm/memory>
+#include <cm3p/uv.h>
+
#include "cmsys/Directory.hxx"
-#include "cmsys/Process.h"
#include "cmCTest.h"
#include "cmCTestBuildCommand.h"
@@ -40,6 +41,8 @@
#include "cmStateSnapshot.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmUVHandlePtr.h"
+#include "cmUVProcessChain.h"
#include "cmValue.h"
#include "cmake.h"
@@ -148,66 +151,65 @@ int cmCTestScriptHandler::ExecuteScript(const std::string& total_script_arg)
// now pass through all the other arguments
std::vector<std::string>& initArgs =
this->CTest->GetInitialCommandLineArguments();
- //*** need to make sure this does not have the current script ***
- for (size_t i = 1; i < initArgs.size(); ++i) {
- argv.push_back(initArgs[i].c_str());
- }
- argv.push_back(nullptr);
// 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(initArgs)
+ .SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT)
+ .SetBuiltinStream(cmUVProcessChainBuilder::Stream_ERROR);
+ auto process = builder.Start();
+ cm::uv_pipe_ptr outPipe;
+ outPipe.init(process.GetLoop(), 0);
+ uv_pipe_open(outPipe, process.OutputStream());
+ cm::uv_pipe_ptr errPipe;
+ errPipe.init(process.GetLoop(), 0);
+ uv_pipe_open(errPipe, process.ErrorStream());
std::vector<char> out;
std::vector<char> err;
std::string line;
- int pipe =
- cmSystemTools::WaitForLine(cp, line, std::chrono::seconds(100), out, err);
- while (pipe != cmsysProcess_Pipe_None) {
+ auto pipe =
+ cmSystemTools::WaitForLine(&process.GetLoop(), outPipe, errPipe, line,
+ std::chrono::seconds(100), out, err);
+ while (pipe != cmSystemTools::WaitForLineResult::None) {
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Output: " << line << "\n");
- if (pipe == cmsysProcess_Pipe_STDERR) {
+ if (pipe == cmSystemTools::WaitForLineResult::STDERR) {
cmCTestLog(this->CTest, ERROR_MESSAGE, line << "\n");
- } else if (pipe == cmsysProcess_Pipe_STDOUT) {
+ } else if (pipe == cmSystemTools::WaitForLineResult::STDOUT) {
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, line << "\n");
}
- pipe = cmSystemTools::WaitForLine(cp, line, std::chrono::seconds(100), out,
- err);
+ pipe =
+ cmSystemTools::WaitForLine(&process.GetLoop(), outPipe, errPipe, line,
+ std::chrono::seconds(100), out, err);
}
// Properly handle output of the build command
- cmsysProcess_WaitForExit(cp, nullptr);
- int result = cmsysProcess_GetState(cp);
+ process.Wait();
+ auto const& status = process.GetStatus(0);
+ auto result = status.GetException();
int retVal = 0;
bool failed = false;
- if (result == cmsysProcess_State_Exited) {
- retVal = cmsysProcess_GetExitValue(cp);
- } else if (result == cmsysProcess_State_Exception) {
- retVal = cmsysProcess_GetExitException(cp);
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "\tThere was an exception: "
- << cmsysProcess_GetExceptionString(cp) << " " << retVal
- << std::endl);
- failed = true;
- } else if (result == cmsysProcess_State_Expired) {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "\tThere was a timeout" << std::endl);
- failed = true;
- } else if (result == cmsysProcess_State_Error) {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "\tError executing ctest: " << cmsysProcess_GetErrorString(cp)
- << std::endl);
- failed = true;
+ switch (result.first) {
+ case cmUVProcessChain::ExceptionCode::None:
+ retVal = static_cast<int>(status.ExitStatus);
+ break;
+ case cmUVProcessChain::ExceptionCode::Spawn:
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "\tError executing ctest: " << result.second << std::endl);
+ failed = true;
+ break;
+ default:
+ retVal = status.TermSignal;
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "\tThere was an exception: " << result.second << " " << retVal
+ << std::endl);
+ failed = true;
}
- cmsysProcess_Delete(cp);
if (failed) {
std::ostringstream message;
message << "Error running command: [";
- message << result << "] ";
+ message << static_cast<int>(result.first) << "] ";
for (const char* arg : argv) {
if (arg) {
message << arg << " ";
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 2bdc928..861ca31 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -31,6 +31,8 @@
#include "cmProcessOutput.h"
#include "cmRange.h"
#include "cmStringAlgorithms.h"
+#include "cmUVHandlePtr.h"
+#include "cmUVStream.h"
#include "cmValue.h"
#if !defined(CMAKE_BOOTSTRAP)
@@ -59,12 +61,14 @@
#include <cassert>
#include <cctype>
#include <cerrno>
+#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <functional>
#include <iostream>
+#include <memory>
#include <sstream>
#include <utility>
#include <vector>
@@ -2213,9 +2217,10 @@ bool cmSystemTools::ListTar(const std::string& outFileName,
#endif
}
-int cmSystemTools::WaitForLine(cmsysProcess* process, std::string& line,
- cmDuration timeout, std::vector<char>& out,
- std::vector<char>& err)
+cmSystemTools::WaitForLineResult cmSystemTools::WaitForLine(
+ uv_loop_t* loop, uv_stream_t* outPipe, uv_stream_t* errPipe,
+ std::string& line, cmDuration timeout, std::vector<char>& out,
+ std::vector<char>& err)
{
line.clear();
auto outiter = out.begin();
@@ -2237,7 +2242,7 @@ int cmSystemTools::WaitForLine(cmsysProcess* process, std::string& line,
line.append(out.data(), length);
}
out.erase(out.begin(), outiter + 1);
- return cmsysProcess_Pipe_STDOUT;
+ return WaitForLineResult::STDOUT;
}
}
@@ -2255,33 +2260,66 @@ int cmSystemTools::WaitForLine(cmsysProcess* process, std::string& line,
line.append(err.data(), length);
}
err.erase(err.begin(), erriter + 1);
- return cmsysProcess_Pipe_STDERR;
+ return WaitForLineResult::STDERR;
}
}
// No newlines found. Wait for more data from the process.
- int length;
- char* data;
- double timeoutAsDbl = timeout.count();
- int pipe =
- cmsysProcess_WaitForData(process, &data, &length, &timeoutAsDbl);
- if (pipe == cmsysProcess_Pipe_Timeout) {
+ struct ReadData
+ {
+ uv_stream_t* Stream;
+ std::vector<char> Buffer;
+ bool Read = false;
+ bool Finished = false;
+ };
+ auto startRead =
+ [](uv_stream_t* stream,
+ ReadData& data) -> std::unique_ptr<cmUVStreamReadHandle> {
+ data.Stream = stream;
+ return cmUVStreamRead(
+ stream,
+ [&data](std::vector<char> buf) {
+ data.Buffer = std::move(buf);
+ data.Read = true;
+ uv_read_stop(data.Stream);
+ },
+ [&data]() { data.Finished = true; });
+ };
+ ReadData outData;
+ auto outHandle = startRead(outPipe, outData);
+ ReadData errData;
+ auto errHandle = startRead(errPipe, errData);
+
+ cm::uv_timer_ptr timer;
+ bool timedOut = false;
+ timer.init(*loop, &timedOut);
+ timer.start(
+ [](uv_timer_t* handle) {
+ auto* timedOutPtr = static_cast<bool*>(handle->data);
+ *timedOutPtr = true;
+ },
+ static_cast<uint64_t>(timeout.count() * 1000.0), 0);
+
+ uv_run(loop, UV_RUN_ONCE);
+ if (timedOut) {
// Timeout has been exceeded.
- return pipe;
+ return WaitForLineResult::Timeout;
}
- if (pipe == cmsysProcess_Pipe_STDOUT) {
- processOutput.DecodeText(data, length, strdata, 1);
+ if (outData.Read) {
+ processOutput.DecodeText(outData.Buffer.data(), outData.Buffer.size(),
+ strdata, 1);
// Append to the stdout buffer.
std::vector<char>::size_type size = out.size();
cm::append(out, strdata);
outiter = out.begin() + size;
- } else if (pipe == cmsysProcess_Pipe_STDERR) {
- processOutput.DecodeText(data, length, strdata, 2);
+ } else if (errData.Read) {
+ processOutput.DecodeText(errData.Buffer.data(), errData.Buffer.size(),
+ strdata, 2);
// Append to the stderr buffer.
std::vector<char>::size_type size = err.size();
cm::append(err, strdata);
erriter = err.begin() + size;
- } else if (pipe == cmsysProcess_Pipe_None) {
+ } else if (outData.Finished && errData.Finished) {
// Both stdout and stderr pipes have broken. Return leftover data.
processOutput.DecodeText(std::string(), strdata, 1);
if (!strdata.empty()) {
@@ -2298,14 +2336,20 @@ int cmSystemTools::WaitForLine(cmsysProcess* process, std::string& line,
if (!out.empty()) {
line.append(out.data(), outiter - out.begin());
out.erase(out.begin(), out.end());
- return cmsysProcess_Pipe_STDOUT;
+ return WaitForLineResult::STDOUT;
}
if (!err.empty()) {
line.append(err.data(), erriter - err.begin());
err.erase(err.begin(), err.end());
- return cmsysProcess_Pipe_STDERR;
+ return WaitForLineResult::STDERR;
}
- return cmsysProcess_Pipe_None;
+ return WaitForLineResult::None;
+ }
+ if (!outData.Finished) {
+ uv_read_stop(outPipe);
+ }
+ if (!errData.Finished) {
+ uv_read_stop(errPipe);
}
}
}
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 9563fd6..c3b8525 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -18,6 +18,8 @@
#include <cm/optional>
#include <cm/string_view>
+#include <cm3p/uv.h>
+
#include "cmsys/Process.h"
#include "cmsys/Status.hxx" // IWYU pragma: export
#include "cmsys/SystemTools.hxx" // IWYU pragma: export
@@ -339,10 +341,20 @@ public:
*/
static void ReportLastSystemError(const char* m);
- /** a general output handler for cmsysProcess */
- static int WaitForLine(cmsysProcess* process, std::string& line,
- cmDuration timeout, std::vector<char>& out,
- std::vector<char>& err);
+ enum class WaitForLineResult
+ {
+ None,
+ STDOUT,
+ STDERR,
+ Timeout,
+ };
+
+ /** a general output handler for libuv */
+ static WaitForLineResult WaitForLine(uv_loop_t* loop, uv_stream_t* outPipe,
+ uv_stream_t* errPipe, std::string& line,
+ cmDuration timeout,
+ std::vector<char>& out,
+ std::vector<char>& err);
static void SetForceUnixPaths(bool v) { s_ForceUnixPaths = v; }
static bool GetForceUnixPaths() { return s_ForceUnixPaths; }
diff --git a/Tests/CMakeLib/testUVProcessChainHelper.cxx b/Tests/CMakeLib/testUVProcessChainHelper.cxx
index fcc45b0..b53cac4 100644
--- a/Tests/CMakeLib/testUVProcessChainHelper.cxx
+++ b/Tests/CMakeLib/testUVProcessChainHelper.cxx
@@ -7,10 +7,6 @@
#include <string>
#include <thread>
-#ifdef _WIN32
-# include <windows.h>
-#endif
-
#include "cmSystemTools.h"
static std::string getStdin()