mirror of
https://github.com/Kitware/CMake.git
synced 2026-03-17 09:11:36 -05:00
cmUVProcessChain: Add Status::SpawnResult field
This commit is contained in:
@@ -35,7 +35,7 @@ bool cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool::GetFileInfo(
|
||||
builder.AddCommand(command);
|
||||
|
||||
auto process = builder.Start();
|
||||
if (!process.Valid()) {
|
||||
if (!process.Valid() || process.GetStatus(0).SpawnResult != 0) {
|
||||
std::ostringstream e;
|
||||
e << "Failed to start objdump process for:\n " << file;
|
||||
this->SetError(e.str());
|
||||
@@ -73,8 +73,7 @@ bool cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool::GetFileInfo(
|
||||
this->SetError(e.str());
|
||||
return false;
|
||||
}
|
||||
auto status = process.GetStatus();
|
||||
if (!status[0] || status[0]->ExitStatus != 0) {
|
||||
if (process.GetStatus(0).ExitStatus != 0) {
|
||||
std::ostringstream e;
|
||||
e << "Failed to run objdump on:\n " << file;
|
||||
this->SetError(e.str());
|
||||
|
||||
@@ -34,7 +34,7 @@ bool cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool::GetFileInfo(
|
||||
.AddCommand(command);
|
||||
|
||||
auto process = builder.Start();
|
||||
if (!process.Valid()) {
|
||||
if (!process.Valid() || process.GetStatus(0).SpawnResult != 0) {
|
||||
std::ostringstream e;
|
||||
e << "Failed to start otool process for:\n " << file;
|
||||
this->SetError(e.str());
|
||||
@@ -88,8 +88,7 @@ bool cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool::GetFileInfo(
|
||||
this->SetError(e.str());
|
||||
return false;
|
||||
}
|
||||
auto status = process.GetStatus();
|
||||
if (!status[0] || status[0]->ExitStatus != 0) {
|
||||
if (process.GetStatus(0).ExitStatus != 0) {
|
||||
std::ostringstream e;
|
||||
e << "Failed to run otool on:\n " << file;
|
||||
this->SetError(e.str());
|
||||
|
||||
@@ -33,7 +33,7 @@ bool cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool::GetFileInfo(
|
||||
builder.AddCommand(command);
|
||||
|
||||
auto process = builder.Start();
|
||||
if (!process.Valid()) {
|
||||
if (!process.Valid() || process.GetStatus(0).SpawnResult != 0) {
|
||||
std::ostringstream e;
|
||||
e << "Failed to start dumpbin process for:\n " << file;
|
||||
this->SetError(e.str());
|
||||
@@ -56,8 +56,7 @@ bool cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool::GetFileInfo(
|
||||
this->SetError(e.str());
|
||||
return false;
|
||||
}
|
||||
auto status = process.GetStatus();
|
||||
if (!status[0] || status[0]->ExitStatus != 0) {
|
||||
if (process.GetStatus(0).ExitStatus != 0) {
|
||||
std::ostringstream e;
|
||||
e << "Failed to run dumpbin on:\n " << file;
|
||||
this->SetError(e.str());
|
||||
|
||||
@@ -34,7 +34,7 @@ bool cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool::GetFileInfo(
|
||||
builder.AddCommand(command);
|
||||
|
||||
auto process = builder.Start();
|
||||
if (!process.Valid()) {
|
||||
if (!process.Valid() || process.GetStatus(0).SpawnResult != 0) {
|
||||
std::ostringstream e;
|
||||
e << "Failed to start objdump process for:\n " << file;
|
||||
this->SetError(e.str());
|
||||
@@ -57,8 +57,7 @@ bool cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool::GetFileInfo(
|
||||
this->SetError(e.str());
|
||||
return false;
|
||||
}
|
||||
auto status = process.GetStatus();
|
||||
if (!status[0] || status[0]->ExitStatus != 0) {
|
||||
if (process.GetStatus(0).ExitStatus != 0) {
|
||||
std::ostringstream e;
|
||||
e << "Failed to run objdump on:\n " << file;
|
||||
this->SetError(e.str());
|
||||
|
||||
@@ -43,7 +43,7 @@ bool cmLDConfigLDConfigTool::GetLDConfigPaths(std::vector<std::string>& paths)
|
||||
builder.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT)
|
||||
.AddCommand(ldConfigCommand);
|
||||
auto process = builder.Start();
|
||||
if (!process.Valid()) {
|
||||
if (!process.Valid() || process.GetStatus(0).SpawnResult != 0) {
|
||||
this->Archive->SetError("Failed to start ldconfig process");
|
||||
return false;
|
||||
}
|
||||
@@ -61,8 +61,7 @@ bool cmLDConfigLDConfigTool::GetLDConfigPaths(std::vector<std::string>& paths)
|
||||
this->Archive->SetError("Failed to wait on ldconfig process");
|
||||
return false;
|
||||
}
|
||||
auto status = process.GetStatus();
|
||||
if (!status[0] || status[0]->ExitStatus != 0) {
|
||||
if (process.GetStatus(0).ExitStatus != 0) {
|
||||
this->Archive->SetError("Failed to run ldconfig");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -53,8 +53,9 @@ struct cmUVProcessChain::InternalData
|
||||
cm::uv_process_ptr Process;
|
||||
cm::uv_pipe_ptr InputPipe;
|
||||
cm::uv_pipe_ptr OutputPipe;
|
||||
bool Finished = false;
|
||||
Status ProcessStatus;
|
||||
|
||||
void Finish();
|
||||
};
|
||||
|
||||
const cmUVProcessChainBuilder* Builder = nullptr;
|
||||
@@ -72,13 +73,11 @@ struct cmUVProcessChain::InternalData
|
||||
std::vector<std::unique_ptr<ProcessData>> Processes;
|
||||
|
||||
bool Prepare(const cmUVProcessChainBuilder* builder);
|
||||
bool SpawnProcess(
|
||||
void SpawnProcess(
|
||||
std::size_t index,
|
||||
const cmUVProcessChainBuilder::ProcessConfiguration& config, bool first,
|
||||
bool last);
|
||||
void Finish();
|
||||
|
||||
static const Status* GetStatus(const ProcessData& data);
|
||||
};
|
||||
|
||||
cmUVProcessChainBuilder::cmUVProcessChainBuilder()
|
||||
@@ -171,10 +170,8 @@ cmUVProcessChain cmUVProcessChainBuilder::Start() const
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
chain.Data->SpawnProcess(i, this->Processes[i], i == 0,
|
||||
i == this->Processes.size() - 1);
|
||||
}
|
||||
|
||||
chain.Data->Finish();
|
||||
@@ -182,15 +179,6 @@ cmUVProcessChain cmUVProcessChainBuilder::Start() const
|
||||
return chain;
|
||||
}
|
||||
|
||||
const cmUVProcessChain::Status* cmUVProcessChain::InternalData::GetStatus(
|
||||
const cmUVProcessChain::InternalData::ProcessData& data)
|
||||
{
|
||||
if (data.Finished) {
|
||||
return &data.ProcessStatus;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool cmUVProcessChain::InternalData::Prepare(
|
||||
const cmUVProcessChainBuilder* builder)
|
||||
{
|
||||
@@ -285,6 +273,7 @@ bool cmUVProcessChain::InternalData::Prepare(
|
||||
this->Processes.emplace_back(cm::make_unique<ProcessData>());
|
||||
auto& process = *this->Processes.back();
|
||||
process.Data = this;
|
||||
process.ProcessStatus.Finished = false;
|
||||
|
||||
if (!first) {
|
||||
auto& prevProcess = *this->Processes[i - 1];
|
||||
@@ -314,7 +303,7 @@ bool cmUVProcessChain::InternalData::Prepare(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmUVProcessChain::InternalData::SpawnProcess(
|
||||
void cmUVProcessChain::InternalData::SpawnProcess(
|
||||
std::size_t index,
|
||||
const cmUVProcessChainBuilder::ProcessConfiguration& config, bool first,
|
||||
bool last)
|
||||
@@ -360,16 +349,17 @@ bool cmUVProcessChain::InternalData::SpawnProcess(
|
||||
options.exit_cb = [](uv_process_t* handle, int64_t exitStatus,
|
||||
int termSignal) {
|
||||
auto* processData = static_cast<ProcessData*>(handle->data);
|
||||
processData->Finished = true;
|
||||
processData->ProcessStatus.ExitStatus = exitStatus;
|
||||
processData->ProcessStatus.TermSignal = termSignal;
|
||||
processData->Data->ProcessesCompleted++;
|
||||
processData->Finish();
|
||||
};
|
||||
|
||||
bool result = process.Process.spawn(*this->Loop, options, &process) >= 0;
|
||||
if ((process.ProcessStatus.SpawnResult =
|
||||
process.Process.spawn(*this->Loop, options, &process)) < 0) {
|
||||
process.Finish();
|
||||
}
|
||||
process.InputPipe.reset();
|
||||
process.OutputPipe.reset();
|
||||
return result;
|
||||
}
|
||||
|
||||
void cmUVProcessChain::InternalData::Finish()
|
||||
@@ -451,19 +441,15 @@ std::vector<const cmUVProcessChain::Status*> cmUVProcessChain::GetStatus()
|
||||
std::vector<const cmUVProcessChain::Status*> statuses(
|
||||
this->Data->Processes.size(), nullptr);
|
||||
for (std::size_t i = 0; i < statuses.size(); i++) {
|
||||
statuses[i] = this->GetStatus(i);
|
||||
statuses[i] = &this->GetStatus(i);
|
||||
}
|
||||
return statuses;
|
||||
}
|
||||
|
||||
const cmUVProcessChain::Status* cmUVProcessChain::GetStatus(
|
||||
const cmUVProcessChain::Status& cmUVProcessChain::GetStatus(
|
||||
std::size_t index) const
|
||||
{
|
||||
auto const& process = *this->Data->Processes[index];
|
||||
if (process.Finished) {
|
||||
return &process.ProcessStatus;
|
||||
}
|
||||
return nullptr;
|
||||
return this->Data->Processes[index]->ProcessStatus;
|
||||
}
|
||||
|
||||
bool cmUVProcessChain::Finished() const
|
||||
@@ -474,8 +460,12 @@ bool cmUVProcessChain::Finished() const
|
||||
std::pair<cmUVProcessChain::ExceptionCode, std::string>
|
||||
cmUVProcessChain::Status::GetException() const
|
||||
{
|
||||
if (this->SpawnResult) {
|
||||
return std::make_pair(ExceptionCode::Spawn,
|
||||
uv_strerror(this->SpawnResult));
|
||||
}
|
||||
#ifdef _WIN32
|
||||
if ((this->ExitStatus & 0xF0000000) == 0xC0000000) {
|
||||
if (this->Finished && (this->ExitStatus & 0xF0000000) == 0xC0000000) {
|
||||
// Child terminated due to exceptional behavior.
|
||||
switch (this->ExitStatus) {
|
||||
case STATUS_CONTROL_C_EXIT:
|
||||
@@ -550,9 +540,8 @@ cmUVProcessChain::Status::GetException() const
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::make_pair(ExceptionCode::None, "");
|
||||
#else
|
||||
if (this->TermSignal) {
|
||||
if (this->Finished && this->TermSignal) {
|
||||
switch (this->TermSignal) {
|
||||
# ifdef SIGSEGV
|
||||
case SIGSEGV:
|
||||
@@ -709,6 +698,12 @@ cmUVProcessChain::Status::GetException() const
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::make_pair(ExceptionCode::None, "");
|
||||
#endif
|
||||
return std::make_pair(ExceptionCode::None, "");
|
||||
}
|
||||
|
||||
void cmUVProcessChain::InternalData::ProcessData::Finish()
|
||||
{
|
||||
this->ProcessStatus.Finished = true;
|
||||
this->Data->ProcessesCompleted++;
|
||||
}
|
||||
|
||||
@@ -74,11 +74,14 @@ public:
|
||||
Illegal,
|
||||
Interrupt,
|
||||
Numerical,
|
||||
Spawn,
|
||||
Other,
|
||||
};
|
||||
|
||||
struct Status
|
||||
{
|
||||
int SpawnResult;
|
||||
bool Finished;
|
||||
int64_t ExitStatus;
|
||||
int TermSignal;
|
||||
|
||||
@@ -102,7 +105,7 @@ public:
|
||||
bool Valid() const;
|
||||
bool Wait(int64_t milliseconds = -1);
|
||||
std::vector<const Status*> GetStatus() const;
|
||||
const Status* GetStatus(std::size_t index) const;
|
||||
const Status& GetStatus(std::size_t index) const;
|
||||
bool Finished() const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -3916,7 +3916,7 @@ std::function<int()> cmake::BuildWorkflowStep(
|
||||
return [builder]() -> int {
|
||||
auto chain = builder.Start();
|
||||
chain.Wait();
|
||||
return static_cast<int>(chain.GetStatus().front()->ExitStatus);
|
||||
return static_cast<int>(chain.GetStatus(0).ExitStatus);
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2008,7 +2008,7 @@ int cmcmd::RunPreprocessor(const std::vector<std::string>& command,
|
||||
.SetBuiltinStream(cmUVProcessChainBuilder::Stream_ERROR)
|
||||
.AddCommand(command);
|
||||
auto process = builder.Start();
|
||||
if (!process.Valid()) {
|
||||
if (!process.Valid() || process.GetStatus(0).SpawnResult != 0) {
|
||||
std::cerr << "Failed to start preprocessor.";
|
||||
return 1;
|
||||
}
|
||||
@@ -2016,8 +2016,7 @@ int cmcmd::RunPreprocessor(const std::vector<std::string>& command,
|
||||
std::cerr << "Failed to wait for preprocessor";
|
||||
return 1;
|
||||
}
|
||||
auto status = process.GetStatus();
|
||||
if (!status[0] || status[0]->ExitStatus != 0) {
|
||||
if (process.GetStatus(0).ExitStatus != 0) {
|
||||
auto* errorStream = process.ErrorStream();
|
||||
if (errorStream) {
|
||||
std::cerr << errorStream->rdbuf();
|
||||
@@ -2130,7 +2129,7 @@ int cmcmd::RunLLVMRC(std::vector<std::string> const& args)
|
||||
.AddCommand(resource_compile);
|
||||
auto process = builder.Start();
|
||||
result = 0;
|
||||
if (!process.Valid()) {
|
||||
if (!process.Valid() || process.GetStatus(0).SpawnResult != 0) {
|
||||
std::cerr << "Failed to start resource compiler.";
|
||||
result = 1;
|
||||
} else {
|
||||
@@ -2144,8 +2143,7 @@ int cmcmd::RunLLVMRC(std::vector<std::string> const& args)
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
auto status = process.GetStatus();
|
||||
if (!status[0] || status[0]->ExitStatus != 0) {
|
||||
if (process.GetStatus(0).ExitStatus != 0) {
|
||||
auto* errorStream = process.ErrorStream();
|
||||
if (errorStream) {
|
||||
std::cerr << errorStream->rdbuf();
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
|
||||
struct ExpectedStatus
|
||||
{
|
||||
bool Finished;
|
||||
bool MatchExitStatus;
|
||||
bool MatchTermSignal;
|
||||
cmUVProcessChain::Status Status;
|
||||
@@ -28,38 +27,6 @@ struct ExpectedStatus
|
||||
std::string ExceptionString;
|
||||
};
|
||||
|
||||
static const std::vector<ExpectedStatus> status1 = {
|
||||
{ false, false, false, { 0, 0 }, cmUVProcessChain::ExceptionCode::None, "" },
|
||||
{ false, false, false, { 0, 0 }, cmUVProcessChain::ExceptionCode::None, "" },
|
||||
{ false, false, false, { 0, 0 }, cmUVProcessChain::ExceptionCode::None, "" },
|
||||
};
|
||||
|
||||
static const std::vector<ExpectedStatus> status2 = {
|
||||
{ true, true, true, { 0, 0 }, cmUVProcessChain::ExceptionCode::None, "" },
|
||||
{ false, false, false, { 0, 0 }, cmUVProcessChain::ExceptionCode::None, "" },
|
||||
{ false, false, false, { 0, 0 }, cmUVProcessChain::ExceptionCode::None, "" },
|
||||
};
|
||||
|
||||
static const std::vector<ExpectedStatus> status3 = {
|
||||
{ true, true, true, { 0, 0 }, cmUVProcessChain::ExceptionCode::None, "" },
|
||||
{ true, true, true, { 1, 0 }, cmUVProcessChain::ExceptionCode::None, "" },
|
||||
#ifdef _WIN32
|
||||
{ true,
|
||||
true,
|
||||
true,
|
||||
{ STATUS_ACCESS_VIOLATION, 0 },
|
||||
cmUVProcessChain::ExceptionCode::Fault,
|
||||
"Access violation" },
|
||||
#else
|
||||
{ true,
|
||||
false,
|
||||
true,
|
||||
{ 0, SIGABRT },
|
||||
cmUVProcessChain::ExceptionCode::Other,
|
||||
"Subprocess aborted" },
|
||||
#endif
|
||||
};
|
||||
|
||||
static const char* ExceptionCodeToString(cmUVProcessChain::ExceptionCode code)
|
||||
{
|
||||
switch (code) {
|
||||
@@ -73,6 +40,8 @@ static const char* ExceptionCodeToString(cmUVProcessChain::ExceptionCode code)
|
||||
return "Interrupt";
|
||||
case cmUVProcessChain::ExceptionCode::Numerical:
|
||||
return "Numerical";
|
||||
case cmUVProcessChain::ExceptionCode::Spawn:
|
||||
return "Spawn";
|
||||
case cmUVProcessChain::ExceptionCode::Other:
|
||||
return "Other";
|
||||
default:
|
||||
@@ -83,9 +52,10 @@ static const char* ExceptionCodeToString(cmUVProcessChain::ExceptionCode code)
|
||||
bool operator==(const cmUVProcessChain::Status* actual,
|
||||
const ExpectedStatus& expected)
|
||||
{
|
||||
if (!expected.Finished) {
|
||||
return !actual;
|
||||
} else if (!actual) {
|
||||
if (expected.Status.SpawnResult != actual->SpawnResult) {
|
||||
return false;
|
||||
}
|
||||
if (expected.Status.Finished != actual->Finished) {
|
||||
return false;
|
||||
}
|
||||
if (expected.MatchExitStatus &&
|
||||
@@ -96,7 +66,7 @@ bool operator==(const cmUVProcessChain::Status* actual,
|
||||
expected.Status.TermSignal != actual->TermSignal) {
|
||||
return false;
|
||||
}
|
||||
if (expected.Finished &&
|
||||
if (expected.Status.Finished &&
|
||||
std::make_pair(expected.ExceptionCode, expected.ExceptionString) !=
|
||||
actual->GetException()) {
|
||||
return false;
|
||||
@@ -150,39 +120,96 @@ static void printResults(
|
||||
{
|
||||
std::cout << "Expected: " << std::endl;
|
||||
for (auto const& e : expected) {
|
||||
if (e.Finished) {
|
||||
std::cout << " ExitStatus: "
|
||||
<< printExpected(e.MatchExitStatus, e.Status.ExitStatus)
|
||||
<< ", TermSignal: "
|
||||
<< printExpected(e.MatchTermSignal, e.Status.TermSignal)
|
||||
<< ", ExceptionCode: "
|
||||
<< printExpected(e.Finished,
|
||||
ExceptionCodeToString(e.ExceptionCode))
|
||||
<< ", ExceptionString: \""
|
||||
<< printExpected(e.Finished, e.ExceptionString) << '"'
|
||||
<< std::endl;
|
||||
} else {
|
||||
std::cout << " null" << std::endl;
|
||||
}
|
||||
std::cout << " SpawnResult: " << e.Status.SpawnResult
|
||||
<< ", Finished: " << e.Status.Finished << ", ExitStatus: "
|
||||
<< printExpected(e.MatchExitStatus, e.Status.ExitStatus)
|
||||
<< ", TermSignal: "
|
||||
<< printExpected(e.MatchTermSignal, e.Status.TermSignal)
|
||||
<< ", ExceptionCode: "
|
||||
<< printExpected(e.Status.Finished,
|
||||
ExceptionCodeToString(e.ExceptionCode))
|
||||
<< ", ExceptionString: \""
|
||||
<< printExpected(e.Status.Finished, e.ExceptionString) << '"'
|
||||
<< std::endl;
|
||||
}
|
||||
std::cout << "Actual:" << std::endl;
|
||||
for (auto const& a : actual) {
|
||||
if (a) {
|
||||
auto exception = a->GetException();
|
||||
std::cout << " ExitStatus: " << a->ExitStatus
|
||||
<< ", TermSignal: " << a->TermSignal << ", ExceptionCode: "
|
||||
<< ExceptionCodeToString(exception.first)
|
||||
<< ", ExceptionString: \"" << exception.second << '"'
|
||||
<< std::endl;
|
||||
} else {
|
||||
std::cout << " null" << std::endl;
|
||||
}
|
||||
auto exception = a->GetException();
|
||||
std::cout << " SpawnResult: " << a->SpawnResult
|
||||
<< ", Finished: " << a->Finished
|
||||
<< ", ExitStatus: " << a->ExitStatus
|
||||
<< ", TermSignal: " << a->TermSignal
|
||||
<< ", ExceptionCode: " << ExceptionCodeToString(exception.first)
|
||||
<< ", ExceptionString: \"" << exception.second << '"'
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
static bool checkExecution(cmUVProcessChainBuilder& builder,
|
||||
std::unique_ptr<cmUVProcessChain>& chain)
|
||||
{
|
||||
static const std::vector<ExpectedStatus> status1 = {
|
||||
{ false,
|
||||
false,
|
||||
{ 0, false, 0, 0 },
|
||||
cmUVProcessChain::ExceptionCode::None,
|
||||
"" },
|
||||
{ false,
|
||||
false,
|
||||
{ 0, false, 0, 0 },
|
||||
cmUVProcessChain::ExceptionCode::None,
|
||||
"" },
|
||||
{ false,
|
||||
false,
|
||||
{ 0, false, 0, 0 },
|
||||
cmUVProcessChain::ExceptionCode::None,
|
||||
"" },
|
||||
};
|
||||
|
||||
static const std::vector<ExpectedStatus> status2 = {
|
||||
{ true,
|
||||
true,
|
||||
{ 0, true, 0, 0 },
|
||||
cmUVProcessChain::ExceptionCode::None,
|
||||
"" },
|
||||
{ false,
|
||||
false,
|
||||
{ 0, false, 0, 0 },
|
||||
cmUVProcessChain::ExceptionCode::None,
|
||||
"" },
|
||||
{ false,
|
||||
false,
|
||||
{ 0, false, 0, 0 },
|
||||
cmUVProcessChain::ExceptionCode::None,
|
||||
"" },
|
||||
};
|
||||
|
||||
static const std::vector<ExpectedStatus> status3 = {
|
||||
{ true,
|
||||
true,
|
||||
{ 0, true, 0, 0 },
|
||||
cmUVProcessChain::ExceptionCode::None,
|
||||
"" },
|
||||
{ true,
|
||||
true,
|
||||
{ 0, true, 1, 0 },
|
||||
cmUVProcessChain::ExceptionCode::None,
|
||||
"" },
|
||||
#ifdef _WIN32
|
||||
{ true,
|
||||
true,
|
||||
{ 0, true, STATUS_ACCESS_VIOLATION, 0 },
|
||||
cmUVProcessChain::ExceptionCode::Fault,
|
||||
"Access violation" },
|
||||
#else
|
||||
{ false,
|
||||
true,
|
||||
{ 0, true, 0, SIGABRT },
|
||||
cmUVProcessChain::ExceptionCode::Other,
|
||||
"Subprocess aborted" },
|
||||
#endif
|
||||
};
|
||||
|
||||
std::vector<const cmUVProcessChain::Status*> status;
|
||||
|
||||
chain = cm::make_unique<cmUVProcessChain>(builder.Start());
|
||||
@@ -201,7 +228,7 @@ static bool checkExecution(cmUVProcessChainBuilder& builder,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (chain->Wait(6000)) {
|
||||
if (chain->Wait(9000)) {
|
||||
std::cout << "Wait() returned true, should be false" << std::endl;
|
||||
return false;
|
||||
}
|
||||
@@ -481,6 +508,113 @@ bool testUVProcessChainCwdChanged(const char* helperCommand)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool testUVProcessChainSpawnFail(const char* helperCommand)
|
||||
{
|
||||
static const std::vector<ExpectedStatus> status1 = {
|
||||
{ false,
|
||||
false,
|
||||
{ 0, false, 0, 0 },
|
||||
cmUVProcessChain::ExceptionCode::None,
|
||||
"" },
|
||||
{ false,
|
||||
false,
|
||||
{ UV_ENOENT, true, 0, 0 },
|
||||
cmUVProcessChain::ExceptionCode::Spawn,
|
||||
uv_strerror(UV_ENOENT) },
|
||||
#ifdef _WIN32
|
||||
{ true,
|
||||
true,
|
||||
{ 0, true, STATUS_ACCESS_VIOLATION, 0 },
|
||||
cmUVProcessChain::ExceptionCode::Fault,
|
||||
"Access violation" },
|
||||
#else
|
||||
{ false,
|
||||
true,
|
||||
{ 0, true, 0, SIGABRT },
|
||||
cmUVProcessChain::ExceptionCode::Other,
|
||||
"Subprocess aborted" },
|
||||
#endif
|
||||
};
|
||||
|
||||
static const std::vector<ExpectedStatus> status2 = {
|
||||
#ifdef _WIN32
|
||||
{ true,
|
||||
true,
|
||||
{ 0, true, 0, 0 },
|
||||
cmUVProcessChain::ExceptionCode::None,
|
||||
"" },
|
||||
#else
|
||||
{ false,
|
||||
true,
|
||||
{ 0, true, 0, SIGPIPE },
|
||||
cmUVProcessChain::ExceptionCode::Other,
|
||||
"SIGPIPE" },
|
||||
#endif
|
||||
{ false,
|
||||
false,
|
||||
{ UV_ENOENT, true, 0, 0 },
|
||||
cmUVProcessChain::ExceptionCode::Spawn,
|
||||
uv_strerror(UV_ENOENT) },
|
||||
#ifdef _WIN32
|
||||
{ true,
|
||||
true,
|
||||
{ 0, true, STATUS_ACCESS_VIOLATION, 0 },
|
||||
cmUVProcessChain::ExceptionCode::Fault,
|
||||
"Access violation" },
|
||||
#else
|
||||
{ false,
|
||||
true,
|
||||
{ 0, true, 0, SIGABRT },
|
||||
cmUVProcessChain::ExceptionCode::Other,
|
||||
"Subprocess aborted" },
|
||||
#endif
|
||||
};
|
||||
|
||||
std::vector<const cmUVProcessChain::Status*> status;
|
||||
|
||||
cmUVProcessChainBuilder builder;
|
||||
builder.AddCommand({ helperCommand, "echo" })
|
||||
.AddCommand({ "this_command_is_for_cmake_and_should_never_exist" })
|
||||
.AddCommand({ helperCommand, "dedup" })
|
||||
.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT)
|
||||
.SetBuiltinStream(cmUVProcessChainBuilder::Stream_ERROR);
|
||||
|
||||
auto chain = builder.Start();
|
||||
if (!chain.Valid()) {
|
||||
std::cout << "Valid() returned false, should be true" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Some platforms, like Solaris 10, take a long time to report a trapped
|
||||
// subprocess to the parent process (about 1.7 seconds in the case of
|
||||
// Solaris 10.) Wait 3 seconds to give it enough time.
|
||||
if (chain.Wait(3000)) {
|
||||
std::cout << "Wait() did not time out" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
status = chain.GetStatus();
|
||||
if (!resultsMatch(status, status1)) {
|
||||
std::cout << "GetStatus() did not produce expected output" << std::endl;
|
||||
printResults(status, status1);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!chain.Wait()) {
|
||||
std::cout << "Wait() timed out" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
status = chain.GetStatus();
|
||||
if (!resultsMatch(status, status2)) {
|
||||
std::cout << "GetStatus() did not produce expected output" << std::endl;
|
||||
printResults(status, status2);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int testUVProcessChain(int argc, char** const argv)
|
||||
{
|
||||
if (argc < 2) {
|
||||
@@ -518,5 +652,10 @@ int testUVProcessChain(int argc, char** const argv)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!testUVProcessChainSpawnFail(argv[1])) {
|
||||
std::cout << "While executing testUVProcessChainSpawnFail().\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -32,13 +32,13 @@ int main(int argc, char** argv)
|
||||
|
||||
std::string command = argv[1];
|
||||
if (command == "echo") {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(3000));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(6000));
|
||||
std::cout << "HELLO world!" << std::flush;
|
||||
std::cerr << "1" << std::flush;
|
||||
return 0;
|
||||
}
|
||||
if (command == "capitalize") {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(9000));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(12000));
|
||||
std::string input = getStdin();
|
||||
for (auto& c : input) {
|
||||
c = static_cast<char>(std::toupper(c));
|
||||
|
||||
Reference in New Issue
Block a user