From 773b304d6f118dda4e1bfce50cbf13293a981aa8 Mon Sep 17 00:00:00 2001 From: Archkon <180910180+Archkon@users.noreply.github.com> Date: Fri, 31 Jul 2026 11:43:34 +0800 Subject: [PATCH] src: copy-construct data when cloning threadsafe COW Initialize the cloned data directly while holding the source read lock, so payloads do not need to be default-constructible or copy-assignable. Signed-off-by: Archkon <180910180+Archkon@users.noreply.github.com> --- src/node_threadsafe_cow-inl.h | 9 +++++---- test/cctest/test_per_process.cc | 17 +++++++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/node_threadsafe_cow-inl.h b/src/node_threadsafe_cow-inl.h index 1cd0055ed807..85698a184f47 100644 --- a/src/node_threadsafe_cow-inl.h +++ b/src/node_threadsafe_cow-inl.h @@ -42,10 +42,11 @@ T* ThreadsafeCopyOnWrite::Write::operator->() { } template -ThreadsafeCopyOnWrite::Impl::Impl(const Impl& other) { - RwLock::ScopedReadLock lock(other.mutex); - data = other.data; -} +ThreadsafeCopyOnWrite::Impl::Impl(const Impl& other) + : data([&other]() { + RwLock::ScopedReadLock lock(other.mutex); + return other.data; + }()) {} } // namespace node diff --git a/test/cctest/test_per_process.cc b/test/cctest/test_per_process.cc index 7a6f53d56222..17e11798c23e 100644 --- a/test/cctest/test_per_process.cc +++ b/test/cctest/test_per_process.cc @@ -6,6 +6,7 @@ #include +using node::ThreadsafeCopyOnWrite; using node::builtins::BuiltinLoader; using node::builtins::BuiltinSourceMap; @@ -18,6 +19,22 @@ class PerProcessTest : public ::testing::Test { namespace { +struct CopyConstructOnly { + explicit CopyConstructOnly(int value) : value(value) {} + CopyConstructOnly() = delete; + CopyConstructOnly(const CopyConstructOnly&) = default; + CopyConstructOnly& operator=(const CopyConstructOnly&) = delete; + + int value; +}; + +TEST(ThreadsafeCopyOnWriteTest, CloneCopyConstructsData) { + const ThreadsafeCopyOnWrite original(42); + auto copy = original; + + EXPECT_EQ(copy.write()->value, 42); +} + TEST_F(PerProcessTest, EmbeddedSources) { const auto& sources = PerProcessTest::get_sources_for_test(); ASSERT_TRUE(std::any_of(sources.cbegin(), sources.cend(), [](auto p) {