summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKyle Edwards <kyle.edwards@kitware.com>2023-08-29 14:50:41 (GMT)
committerKitware Robot <kwrobot@kitware.com>2023-08-29 14:50:58 (GMT)
commitb938e7de9c21986a67dc54852ac971e5e1499be6 (patch)
tree4c864a3ecca4c606b7eb3adb86a00622071cfbec
parent9844219878165b468bc0d7cb48ea71393703e904 (diff)
parent27be5ccd45500c055288d4d4cfcdb675eca38fee (diff)
downloadCMake-b938e7de9c21986a67dc54852ac971e5e1499be6.zip
CMake-b938e7de9c21986a67dc54852ac971e5e1499be6.tar.gz
CMake-b938e7de9c21986a67dc54852ac971e5e1499be6.tar.bz2
Merge topic 'cmuvstreamread-raii'
27be5ccd45 cmUVStreamRead: Return RAII handle to avoid memory leak Acked-by: Kitware Robot <kwrobot@kitware.com> Acked-by: buildbot <buildbot@kitware.com> Merge-request: !8749
-rw-r--r--Source/cmUVStream.h40
-rw-r--r--Tests/CMakeLib/testUVStreambuf.cxx58
2 files changed, 83 insertions, 15 deletions
diff --git a/Source/cmUVStream.h b/Source/cmUVStream.h
index 5998256..db051b8 100644
--- a/Source/cmUVStream.h
+++ b/Source/cmUVStream.h
@@ -3,8 +3,11 @@
#pragma once
#include <cassert>
+#include <functional>
#include <istream>
+#include <cm/memory>
+
#include <cm3p/uv.h>
#include "cmUVHandlePtr.h"
@@ -104,28 +107,38 @@ void cmBasicUVPipeIStream<CharT, Traits>::close()
using cmUVPipeIStream = cmBasicUVPipeIStream<char>;
+class cmUVStreamReadHandle
+{
+private:
+ std::vector<char> Buffer;
+ std::function<void(std::vector<char>)> OnRead;
+ std::function<void()> OnFinish;
+
+ template <typename ReadCallback, typename FinishCallback>
+ friend std::unique_ptr<cmUVStreamReadHandle> cmUVStreamRead(
+ uv_stream_t* stream, ReadCallback onRead, FinishCallback onFinish);
+};
+
template <typename ReadCallback, typename FinishCallback>
-void cmUVStreamRead(uv_stream_t* stream, ReadCallback onRead,
- FinishCallback onFinish)
+std::unique_ptr<cmUVStreamReadHandle> cmUVStreamRead(uv_stream_t* stream,
+ ReadCallback onRead,
+ FinishCallback onFinish)
{
- struct ReadData
- {
- std::vector<char> Buffer;
- ReadCallback OnRead;
- FinishCallback OnFinish;
- };
-
- stream->data = new ReadData{ {}, std::move(onRead), std::move(onFinish) };
+ auto handle = cm::make_unique<cmUVStreamReadHandle>();
+ handle->OnRead = std::move(onRead);
+ handle->OnFinish = std::move(onFinish);
+
+ stream->data = handle.get();
uv_read_start(
stream,
[](uv_handle_t* s, std::size_t suggestedSize, uv_buf_t* buffer) {
- auto* data = static_cast<ReadData*>(s->data);
+ auto* data = static_cast<cmUVStreamReadHandle*>(s->data);
data->Buffer.resize(suggestedSize);
buffer->base = data->Buffer.data();
buffer->len = suggestedSize;
},
[](uv_stream_t* s, ssize_t nread, const uv_buf_t* buffer) {
- auto* data = static_cast<ReadData*>(s->data);
+ auto* data = static_cast<cmUVStreamReadHandle*>(s->data);
if (nread > 0) {
(void)buffer;
assert(buffer->base == data->Buffer.data());
@@ -134,7 +147,8 @@ void cmUVStreamRead(uv_stream_t* stream, ReadCallback onRead,
} else if (nread < 0 /*|| nread == UV_EOF*/) {
data->OnFinish();
uv_read_stop(s);
- delete data;
}
});
+
+ return handle;
}
diff --git a/Tests/CMakeLib/testUVStreambuf.cxx b/Tests/CMakeLib/testUVStreambuf.cxx
index f3977d4..af06a8e 100644
--- a/Tests/CMakeLib/testUVStreambuf.cxx
+++ b/Tests/CMakeLib/testUVStreambuf.cxx
@@ -503,7 +503,7 @@ bool testUVStreamRead()
std::string output;
bool finished = false;
- cmUVStreamRead(
+ auto handle = cmUVStreamRead(
pipeSource,
[&output](std::vector<char> data) { cm::append(output, data); },
[&output, &finished]() {
@@ -524,6 +524,55 @@ bool testUVStreamRead()
return true;
}
+bool testUVStreamReadLeak()
+{
+ int pipe[] = { -1, -1 };
+ if (cmGetPipes(pipe) < 0) {
+ std::cout << "cmGetPipes() returned an error" << std::endl;
+ return false;
+ }
+
+ cm::uv_loop_ptr loop;
+ loop.init();
+ cm::uv_pipe_ptr pipeSink;
+ pipeSink.init(*loop, 0);
+ uv_pipe_open(pipeSink, pipe[1]);
+
+ std::string str = "Hello world!";
+ uv_write_t writeReq;
+ uv_buf_t buf;
+ buf.base = &str.front();
+ buf.len = str.length();
+ uv_write(&writeReq, pipeSink, &buf, 1, nullptr);
+ uv_run(loop, UV_RUN_DEFAULT);
+ pipeSink.reset();
+
+ cm::uv_pipe_ptr pipeSource;
+ pipeSource.init(*loop, 0);
+ uv_pipe_open(pipeSource, pipe[0]);
+
+ std::string output;
+ bool finished = false;
+ auto handle = cmUVStreamRead(
+ pipeSource,
+ [&output](std::vector<char> data) { cm::append(output, data); },
+ [&output, &finished]() {
+ if (output != "Hello world!") {
+ std::cout << "Output was \"" << output
+ << "\", should be \"Hello world!\"" << std::endl;
+ return;
+ }
+ finished = true;
+ });
+
+ if (finished) {
+ std::cout << "finished was set" << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
int testUVStreambuf(int argc, char** const argv)
{
if (argc < 2) {
@@ -547,7 +596,12 @@ int testUVStreambuf(int argc, char** const argv)
}
if (!testUVStreamRead()) {
- std::cout << "While executing testUVPipeIStream().\n";
+ std::cout << "While executing testUVStreamRead().\n";
+ return -1;
+ }
+
+ if (!testUVStreamReadLeak()) {
+ std::cout << "While executing testUVStreamReadLeak().\n";
return -1;
}