Merge pull request #49663 from CurtizJ/fix-race-context-copy

Fix race in `Context::createCopy`
This commit is contained in:
Anton Popov 2023-05-10 02:11:35 +02:00 committed by GitHub
commit 862008da0d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 52 additions and 1 deletions

View File

@ -669,13 +669,15 @@ SharedContextHolder Context::createShared()
ContextMutablePtr Context::createCopy(const ContextPtr & other)
{
auto lock = other->getLock();
return std::shared_ptr<Context>(new Context(*other));
}
ContextMutablePtr Context::createCopy(const ContextWeakPtr & other)
{
auto ptr = other.lock();
if (!ptr) throw Exception(ErrorCodes::LOGICAL_ERROR, "Can't copy an expired context");
if (!ptr)
throw Exception(ErrorCodes::LOGICAL_ERROR, "Can't copy an expired context");
return createCopy(ptr);
}

View File

@ -0,0 +1,49 @@
#include <Interpreters/Context.h>
#include <Common/tests/gtest_global_context.h>
#include <gtest/gtest.h>
using namespace DB;
template <typename Ptr>
void run(Ptr context)
{
for (size_t i = 0; i < 100; ++i)
{
std::thread t1([context]
{
if constexpr (std::is_same_v<ContextWeakPtr, Ptr>)
context.lock()->getAsyncReadCounters();
else
context->getAsyncReadCounters();
});
std::thread t2([context]
{
Context::createCopy(context);
});
t1.join();
t2.join();
}
}
TEST(Context, MutableRace)
{
auto context = Context::createCopy(getContext().context);
context->makeQueryContext();
run<ContextMutablePtr>(context);
}
TEST(Context, ConstRace)
{
auto context = Context::createCopy(getContext().context);
context->makeQueryContext();
run<ContextPtr>(context);
}
TEST(Context, WeakRace)
{
auto context = Context::createCopy(getContext().context);
context->makeQueryContext();
run<ContextWeakPtr>(context);
}