更新 src/redis.cpp
This commit is contained in:
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user