diff options
author | Kyle Edwards <kyle.edwards@kitware.com> | 2023-07-25 19:12:33 (GMT) |
---|---|---|
committer | Kyle Edwards <kyle.edwards@kitware.com> | 2023-08-29 14:51:30 (GMT) |
commit | 50a6e78a8295ac89149639839cebc3b61f2f9db3 (patch) | |
tree | 91818dd3640f688ae3a6b76ddbce808acb8ab4f3 /Source | |
parent | 49a37d5a97ccd6e59b9e205a96b9dec251708f76 (diff) | |
download | CMake-50a6e78a8295ac89149639839cebc3b61f2f9db3.zip CMake-50a6e78a8295ac89149639839cebc3b61f2f9db3.tar.gz CMake-50a6e78a8295ac89149639839cebc3b61f2f9db3.tar.bz2 |
cmSystemTools::RunSingleCommand(): Replace cmsysProcess with cmUVProcessChain
And pass OUTPUT_PASSTHROUGH in one call where it was missing.
Diffstat (limited to 'Source')
-rw-r--r-- | Source/cmSystemTools.cxx | 202 | ||||
-rw-r--r-- | Source/cmSystemTools.h | 1 | ||||
-rw-r--r-- | Source/cmcmd.cxx | 3 |
3 files changed, 116 insertions, 90 deletions
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 861ca31..fe421ba 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -25,6 +25,8 @@ #include <cm3p/uv.h> +#include "cm_fileno.hxx" + #include "cmDuration.h" #include "cmELF.h" #include "cmMessageMetadata.h" @@ -32,6 +34,7 @@ #include "cmRange.h" #include "cmStringAlgorithms.h" #include "cmUVHandlePtr.h" +#include "cmUVProcessChain.h" #include "cmUVStream.h" #include "cmValue.h" @@ -572,85 +575,113 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command, const char* dir, OutputOption outputflag, cmDuration timeout, Encoding encoding) { - std::vector<const char*> argv; - argv.reserve(command.size() + 1); - for (std::string const& cmd : command) { - argv.push_back(cmd.c_str()); - } - argv.push_back(nullptr); - - cmsysProcess* cp = cmsysProcess_New(); - cmsysProcess_SetCommand(cp, argv.data()); - cmsysProcess_SetWorkingDirectory(cp, dir); - if (cmSystemTools::GetRunCommandHideConsole()) { - cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1); + cmUVProcessChainBuilder builder; + builder.AddCommand(command); + if (dir) { + builder.SetWorkingDirectory(dir); } if (outputflag == OUTPUT_PASSTHROUGH) { - cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDOUT, 1); - cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDERR, 1); captureStdOut = nullptr; captureStdErr = nullptr; + builder + .SetExternalStream(cmUVProcessChainBuilder::Stream_OUTPUT, + cm_fileno(stdout)) + .SetExternalStream(cmUVProcessChainBuilder::Stream_ERROR, + cm_fileno(stderr)); } else if (outputflag == OUTPUT_MERGE || (captureStdErr && captureStdErr == captureStdOut)) { - cmsysProcess_SetOption(cp, cmsysProcess_Option_MergeOutput, 1); + builder.SetMergedBuiltinStreams(); captureStdErr = nullptr; + } else { + builder.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT) + .SetBuiltinStream(cmUVProcessChainBuilder::Stream_ERROR); } assert(!captureStdErr || captureStdErr != captureStdOut); - cmsysProcess_SetTimeout(cp, timeout.count()); - cmsysProcess_Execute(cp); + auto chain = builder.Start(); + bool timedOut = false; + cm::uv_timer_ptr timer; + if (timeout.count()) { + timer.init(chain.GetLoop(), &timedOut); + timer.start( + [](uv_timer_t* t) { + auto* timedOutPtr = static_cast<bool*>(t->data); + *timedOutPtr = true; + }, + static_cast<uint64_t>(timeout.count() * 1000.0), 0); + } std::vector<char> tempStdOut; std::vector<char> tempStdErr; - char* data; - int length; - int pipe; + cm::uv_pipe_ptr outStream; + bool outFinished = true; + cm::uv_pipe_ptr errStream; + bool errFinished = true; cmProcessOutput processOutput(encoding); - std::string strdata; + std::unique_ptr<cmUVStreamReadHandle> outputHandle; + std::unique_ptr<cmUVStreamReadHandle> errorHandle; if (outputflag != OUTPUT_PASSTHROUGH && (captureStdOut || captureStdErr || outputflag != OUTPUT_NONE)) { - while ((pipe = cmsysProcess_WaitForData(cp, &data, &length, nullptr)) > - 0) { - // Translate NULL characters in the output into valid text. - for (int i = 0; i < length; ++i) { - if (data[i] == '\0') { - data[i] = ' '; - } + auto startRead = + [&outputflag, &processOutput, + &chain](cm::uv_pipe_ptr& pipe, int stream, std::string* captureStd, + std::vector<char>& tempStd, int id, + void (*outputFunc)(const std::string&), + bool& finished) -> std::unique_ptr<cmUVStreamReadHandle> { + if (stream < 0) { + return nullptr; } - if (pipe == cmsysProcess_Pipe_STDOUT) { - if (outputflag != OUTPUT_NONE) { - processOutput.DecodeText(data, length, strdata, 1); - cmSystemTools::Stdout(strdata); - } - if (captureStdOut) { - cm::append(tempStdOut, data, data + length); - } - } else if (pipe == cmsysProcess_Pipe_STDERR) { - if (outputflag != OUTPUT_NONE) { - processOutput.DecodeText(data, length, strdata, 2); - cmSystemTools::Stderr(strdata); - } - if (captureStdErr) { - cm::append(tempStdErr, data, data + length); - } - } - } + pipe.init(chain.GetLoop(), 0); + uv_pipe_open(pipe, stream); - if (outputflag != OUTPUT_NONE) { - processOutput.DecodeText(std::string(), strdata, 1); - if (!strdata.empty()) { - cmSystemTools::Stdout(strdata); - } - processOutput.DecodeText(std::string(), strdata, 2); - if (!strdata.empty()) { - cmSystemTools::Stderr(strdata); - } + finished = false; + return cmUVStreamRead( + pipe, + [outputflag, &processOutput, captureStd, &tempStd, id, + outputFunc](std::vector<char> data) { + // Translate NULL characters in the output into valid text. + for (auto& c : data) { + if (c == '\0') { + c = ' '; + } + } + + if (outputflag != OUTPUT_NONE) { + std::string strdata; + processOutput.DecodeText(data.data(), data.size(), strdata, id); + outputFunc(strdata); + } + if (captureStd) { + cm::append(tempStd, data.data(), data.data() + data.size()); + } + }, + [&finished, outputflag, &processOutput, id, outputFunc]() { + finished = true; + if (outputflag != OUTPUT_NONE) { + std::string strdata; + processOutput.DecodeText(std::string(), strdata, id); + if (!strdata.empty()) { + outputFunc(strdata); + } + } + }); + }; + + outputHandle = + startRead(outStream, chain.OutputStream(), captureStdOut, tempStdOut, 1, + cmSystemTools::Stdout, outFinished); + if (chain.OutputStream() != chain.ErrorStream()) { + errorHandle = + startRead(errStream, chain.ErrorStream(), captureStdErr, tempStdErr, 2, + cmSystemTools::Stderr, errFinished); } } - cmsysProcess_WaitForExit(cp, nullptr); + while (!timedOut && !(chain.Finished() && outFinished && errFinished)) { + uv_run(&chain.GetLoop(), UV_RUN_ONCE); + } if (captureStdOut) { captureStdOut->assign(tempStdOut.begin(), tempStdOut.end()); @@ -662,37 +693,7 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command, } bool result = true; - if (cmsysProcess_GetState(cp) == cmsysProcess_State_Exited) { - if (retVal) { - *retVal = cmsysProcess_GetExitValue(cp); - } else { - if (cmsysProcess_GetExitValue(cp) != 0) { - result = false; - } - } - } else if (cmsysProcess_GetState(cp) == cmsysProcess_State_Exception) { - const char* exception_str = cmsysProcess_GetExceptionString(cp); - if (outputflag != OUTPUT_NONE) { - std::cerr << exception_str << std::endl; - } - if (captureStdErr) { - captureStdErr->append(exception_str, strlen(exception_str)); - } else if (captureStdOut) { - captureStdOut->append(exception_str, strlen(exception_str)); - } - result = false; - } else if (cmsysProcess_GetState(cp) == cmsysProcess_State_Error) { - const char* error_str = cmsysProcess_GetErrorString(cp); - if (outputflag != OUTPUT_NONE) { - std::cerr << error_str << std::endl; - } - if (captureStdErr) { - captureStdErr->append(error_str, strlen(error_str)); - } else if (captureStdOut) { - captureStdOut->append(error_str, strlen(error_str)); - } - result = false; - } else if (cmsysProcess_GetState(cp) == cmsysProcess_State_Expired) { + if (timedOut) { const char* error_str = "Process terminated due to timeout\n"; if (outputflag != OUTPUT_NONE) { std::cerr << error_str << std::endl; @@ -701,9 +702,34 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command, captureStdErr->append(error_str, strlen(error_str)); } result = false; + } else { + 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); + } else { + if (status.ExitStatus != 0) { + result = false; + } + } + break; + default: { + if (outputflag != OUTPUT_NONE) { + std::cerr << exception.second << std::endl; + } + if (captureStdErr) { + captureStdErr->append(exception.second); + } else if (captureStdOut) { + captureStdOut->append(exception.second); + } + result = false; + } break; + } } - cmsysProcess_Delete(cp); return result; } diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index c3b8525..7e33e58 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -20,7 +20,6 @@ #include <cm3p/uv.h> -#include "cmsys/Process.h" #include "cmsys/Status.hxx" // IWYU pragma: export #include "cmsys/SystemTools.hxx" // IWYU pragma: export diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index e8742b2..94f4d38 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -1107,7 +1107,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args, int ret = 0; auto time_start = std::chrono::steady_clock::now(); - cmSystemTools::RunSingleCommand(command, nullptr, nullptr, &ret); + cmSystemTools::RunSingleCommand(command, nullptr, nullptr, &ret, nullptr, + cmSystemTools::OUTPUT_PASSTHROUGH); auto time_finish = std::chrono::steady_clock::now(); std::chrono::duration<double> time_elapsed = time_finish - time_start; |