From c10119df62cf212f9274c6a5c0af609bae4f1b03 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 16 Jan 2018 13:59:55 -0500 Subject: CTest: Fix decoding of MBCS character split by buffering Use a single `cmProcessOutput` instance persistently to decode all output of a test process so that partial character bytes can be buffered. --- Source/CTest/cmProcess.cxx | 15 +++++++-------- Source/CTest/cmProcess.h | 4 +++- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx index c8806a7..4454715 100644 --- a/Source/CTest/cmProcess.cxx +++ b/Source/CTest/cmProcess.cxx @@ -5,19 +5,19 @@ #include "cmCTest.h" #include "cmCTestRunTest.h" #include "cmCTestTestHandler.h" -#include "cmProcessOutput.h" #include "cmsys/Process.h" #include #include #include #include -#include #include #if !defined(_WIN32) #include #endif +#define CM_PROCESS_BUF_SIZE 65536 + #if defined(_WIN32) && !defined(__CYGWIN__) #include @@ -60,6 +60,7 @@ static int cmProcessGetPipes(int* fds) cmProcess::cmProcess(cmCTestRunTest& runner) : Runner(runner) + , Conv(cmProcessOutput::UTF8, CM_PROCESS_BUF_SIZE) { this->Timeout = std::chrono::duration::zero(); this->TotalTime = std::chrono::duration::zero(); @@ -232,9 +233,7 @@ void cmProcess::OnRead(ssize_t nread, const uv_buf_t* buf) std::string line; if (nread > 0) { std::string strdata; - cmProcessOutput processOutput(cmProcessOutput::UTF8, - static_cast(buf->len)); - processOutput.DecodeText(buf->base, static_cast(nread), strdata); + this->Conv.DecodeText(buf->base, static_cast(nread), strdata); this->Output.insert(this->Output.end(), strdata.begin(), strdata.end()); while (this->Output.GetLine(line)) { @@ -271,10 +270,10 @@ void cmProcess::OnAllocateCB(uv_handle_t* handle, size_t suggested_size, self->OnAllocate(suggested_size, buf); } -void cmProcess::OnAllocate(size_t suggested_size, uv_buf_t* buf) +void cmProcess::OnAllocate(size_t /*suggested_size*/, uv_buf_t* buf) { - if (this->Buf.size() < suggested_size) { - this->Buf.resize(suggested_size); + if (this->Buf.size() != CM_PROCESS_BUF_SIZE) { + this->Buf.resize(CM_PROCESS_BUF_SIZE); } *buf = diff --git a/Source/CTest/cmProcess.h b/Source/CTest/cmProcess.h index 9250896..633be24 100644 --- a/Source/CTest/cmProcess.h +++ b/Source/CTest/cmProcess.h @@ -5,13 +5,14 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include "cmProcessOutput.h" #include "cmUVHandlePtr.h" #include "cm_uv.h" #include #include +#include #include -#include #include class cmCTestRunTest; @@ -80,6 +81,7 @@ private: std::vector Buf; cmCTestRunTest& Runner; + cmProcessOutput Conv; int Signal = 0; cmProcess::State ProcessState = cmProcess::State::Starting; -- cgit v0.12 From a6e9b9c9e4460f77fc173a3610b167e15f66f4ec Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 17 Jan 2018 11:17:28 -0500 Subject: CTest: Fix process output read error cases The libuv documentation states that the stream read callback may be called with `nread == 0` for EAGAIN. Handle this gracefully. It also states that the callee is responsible for closing the stream on error. Always close the stream for `nread < 0`. --- Source/CTest/cmProcess.cxx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx index 4454715..e332a77 100644 --- a/Source/CTest/cmProcess.cxx +++ b/Source/CTest/cmProcess.cxx @@ -244,6 +244,10 @@ void cmProcess::OnRead(ssize_t nread, const uv_buf_t* buf) return; } + if (nread == 0) { + return; + } + // The process will provide no more data. if (nread != UV_EOF) { auto error = static_cast(nread); @@ -257,6 +261,7 @@ void cmProcess::OnRead(ssize_t nread, const uv_buf_t* buf) } this->ReadHandleClosed = true; + this->PipeReader.reset(); if (this->ProcessHandleClosed) { uv_timer_stop(this->Timer); this->Runner.FinalizeTest(); -- cgit v0.12