summaryrefslogtreecommitdiffstats
path: root/Source/cmUVProcessChain.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmUVProcessChain.cxx')
-rw-r--r--Source/cmUVProcessChain.cxx91
1 files changed, 68 insertions, 23 deletions
diff --git a/Source/cmUVProcessChain.cxx b/Source/cmUVProcessChain.cxx
index 436ada2..6517e60 100644
--- a/Source/cmUVProcessChain.cxx
+++ b/Source/cmUVProcessChain.cxx
@@ -5,11 +5,9 @@
#include "cmUVProcessChain.h"
#include <array>
-#include <cassert>
#include <csignal>
#include <cstdio>
#include <istream> // IWYU pragma: keep
-#include <iterator>
#include <type_traits>
#include <utility>
@@ -53,6 +51,7 @@ struct cmUVProcessChain::InternalData
{
cmUVProcessChain::InternalData* Data;
cm::uv_process_ptr Process;
+ cm::uv_pipe_ptr InputPipe;
cm::uv_pipe_ptr OutputPipe;
bool Finished = false;
Status ProcessStatus;
@@ -66,14 +65,17 @@ struct cmUVProcessChain::InternalData
StreamData<std::istream> OutputStreamData;
StreamData<std::istream> ErrorStreamData;
+ cm::uv_pipe_ptr TempOutputPipe;
cm::uv_pipe_ptr TempErrorPipe;
unsigned int ProcessesCompleted = 0;
std::vector<std::unique_ptr<ProcessData>> Processes;
bool Prepare(const cmUVProcessChainBuilder* builder);
- bool AddCommand(const cmUVProcessChainBuilder::ProcessConfiguration& config,
- bool first, bool last);
+ bool SpawnProcess(
+ std::size_t index,
+ const cmUVProcessChainBuilder::ProcessConfiguration& config, bool first,
+ bool last);
void Finish();
static const Status* GetStatus(const ProcessData& data);
@@ -168,9 +170,9 @@ cmUVProcessChain cmUVProcessChainBuilder::Start() const
return chain;
}
- for (auto it = this->Processes.begin(); it != this->Processes.end(); ++it) {
- if (!chain.Data->AddCommand(*it, it == this->Processes.begin(),
- it == std::prev(this->Processes.end()))) {
+ for (std::size_t i = 0; i < this->Processes.size(); i++) {
+ if (!chain.Data->SpawnProcess(i, this->Processes[i], i == 0,
+ i == this->Processes.size() - 1)) {
return chain;
}
}
@@ -247,12 +249,27 @@ bool cmUVProcessChain::InternalData::Prepare(
outputData.Stdio.flags = UV_INHERIT_FD;
outputData.Stdio.data.fd = errorData.Stdio.data.fd;
} else {
+ int pipeFd[2];
+ if (cmGetPipes(pipeFd) < 0) {
+ return false;
+ }
+
if (outputData.BuiltinStream.init(*this->Loop, 0) < 0) {
return false;
}
- outputData.Stdio.flags =
- static_cast<uv_stdio_flags>(UV_CREATE_PIPE | UV_WRITABLE_PIPE);
- outputData.Stdio.data.stream = outputData.BuiltinStream;
+ if (uv_pipe_open(outputData.BuiltinStream, pipeFd[0]) < 0) {
+ return false;
+ }
+ outputData.Stdio.flags = UV_INHERIT_FD;
+ outputData.Stdio.data.fd = pipeFd[1];
+
+ if (this->TempOutputPipe.init(*this->Loop, 0) < 0) {
+ return false;
+ }
+ if (uv_pipe_open(this->TempOutputPipe, outputData.Stdio.data.fd) < 0) {
+ return false;
+ }
+
outputData.Streambuf.open(outputData.BuiltinStream);
}
break;
@@ -263,16 +280,46 @@ bool cmUVProcessChain::InternalData::Prepare(
break;
}
+ bool first = true;
+ for (std::size_t i = 0; i < this->Builder->Processes.size(); i++) {
+ this->Processes.emplace_back(cm::make_unique<ProcessData>());
+ auto& process = *this->Processes.back();
+ process.Data = this;
+
+ if (!first) {
+ auto& prevProcess = *this->Processes[i - 1];
+
+ int pipeFd[2];
+ if (cmGetPipes(pipeFd) < 0) {
+ return false;
+ }
+
+ if (prevProcess.OutputPipe.init(*this->Loop, 0) < 0) {
+ return false;
+ }
+ if (uv_pipe_open(prevProcess.OutputPipe, pipeFd[1]) < 0) {
+ return false;
+ }
+ if (process.InputPipe.init(*this->Loop, 0) < 0) {
+ return false;
+ }
+ if (uv_pipe_open(process.InputPipe, pipeFd[0]) < 0) {
+ return false;
+ }
+ }
+
+ first = false;
+ }
+
return true;
}
-bool cmUVProcessChain::InternalData::AddCommand(
+bool cmUVProcessChain::InternalData::SpawnProcess(
+ std::size_t index,
const cmUVProcessChainBuilder::ProcessConfiguration& config, bool first,
bool last)
{
- this->Processes.emplace_back(cm::make_unique<ProcessData>());
- auto& process = *this->Processes.back();
- process.Data = this;
+ auto& process = *this->Processes[index];
auto options = uv_process_options_t();
@@ -296,20 +343,14 @@ bool cmUVProcessChain::InternalData::AddCommand(
if (first) {
stdio[0].flags = UV_IGNORE;
} else {
- assert(this->Processes.size() >= 2);
- auto& prev = *this->Processes[this->Processes.size() - 2];
stdio[0].flags = UV_INHERIT_STREAM;
- stdio[0].data.stream = prev.OutputPipe;
+ stdio[0].data.stream = process.InputPipe;
}
if (last) {
stdio[1] = this->OutputStreamData.Stdio;
} else {
- if (process.OutputPipe.init(*this->Loop, 0) < 0) {
- return false;
- }
stdio[1] = uv_stdio_container_t();
- stdio[1].flags =
- static_cast<uv_stdio_flags>(UV_CREATE_PIPE | UV_WRITABLE_PIPE);
+ stdio[1].flags = UV_INHERIT_STREAM;
stdio[1].data.stream = process.OutputPipe;
}
stdio[2] = this->ErrorStreamData.Stdio;
@@ -325,11 +366,15 @@ bool cmUVProcessChain::InternalData::AddCommand(
processData->Data->ProcessesCompleted++;
};
- return process.Process.spawn(*this->Loop, options, &process) >= 0;
+ bool result = process.Process.spawn(*this->Loop, options, &process) >= 0;
+ process.InputPipe.reset();
+ process.OutputPipe.reset();
+ return result;
}
void cmUVProcessChain::InternalData::Finish()
{
+ this->TempOutputPipe.reset();
this->TempErrorPipe.reset();
this->Valid = true;
}