更新 src/redis.cpp

This commit is contained in:
2026-08-04 13:16:24 +08:00
parent 0209f28397
commit 8487a299bb

View File

@@ -45,22 +45,34 @@ void module::redis_pool::close()
std::shared_ptr<module::redis> module::redis_pool::get() std::shared_ptr<module::redis> module::redis_pool::get()
{ {
if (m_closed)
{
throw ylib::exception("connection pool is closed");
}
redisContext* ctx = nullptr; redisContext* ctx = nullptr;
if (m_queue.pop(ctx))
{ {
std::unique_lock<std::mutex> uni(m_mutex);
if (m_closed)
{
throw ylib::exception("connection pool is closed");
}
if (m_queue.pop(ctx))
{
m_pop_size++;
return std::make_shared<module::redis>(ctx, this);
}
if (m_pop_size >= m_max_size)
throw ylib::exception("connection pool releases more connections than the maximum number");
// Reserve a slot before unlocking for the blocking connect.
m_pop_size++; m_pop_size++;
return std::make_shared<module::redis>(ctx, this);
} }
if (m_pop_size >= m_max_size)
throw ylib::exception("connection pool releases more connections than the maximum number");
ctx = reget(nullptr); try
{
m_pop_size++; ctx = reget(nullptr);
}
catch (...)
{
std::unique_lock<std::mutex> uni(m_mutex);
m_pop_size--;
throw;
}
return std::make_shared<module::redis>(ctx, this); return std::make_shared<module::redis>(ctx, this);
} }
@@ -170,13 +182,15 @@ void module::redis_pool::recover(redisContext* ctx)
{ {
if (ctx == nullptr) if (ctx == nullptr)
return; return;
std::unique_lock<std::mutex> uni(m_mutex);
if (m_closed) if (m_closed)
{ {
redisFree(ctx); redisFree(ctx);
return; return;
} }
m_queue.push(ctx); m_queue.push(ctx);
m_pop_size--; if (m_pop_size > 0)
m_pop_size--;
} }
module::redis::redis(redisContext* context, redis_pool* pool):m_context(context),m_pool(pool) module::redis::redis(redisContext* context, redis_pool* pool):m_context(context),m_pool(pool)
@@ -190,7 +204,14 @@ module::redis::~redis()
} }
void module::redis::close() void module::redis::close()
{ {
m_pool->recover(m_context); // Guard against double-return: Lua close() + shared_ptr destructor
// previously pushed the same redisContext* into the pool twice, which
// leads to concurrent redisCommand use and "double free or corruption".
if (m_context == nullptr || m_pool == nullptr)
return;
redisContext* ctx = m_context;
m_context = nullptr;
m_pool->recover(ctx);
} }
sol::object module::redis::command(const std::string& cmd, sol::this_state ts) sol::object module::redis::command(const std::string& cmd, sol::this_state ts)
{ {