fix(server): Fix SCAN deadlock (#3235)

This commit is contained in:
Vladislav 2024-06-30 09:15:14 +03:00 committed by GitHub
parent 4cc9834d89
commit c34a78966a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 15 additions and 4 deletions

View File

@ -609,10 +609,16 @@ uint64_t ScanGeneric(uint64_t cursor, const ScanOpts& scan_opts, StringVec* keys
DbContext db_cntx{cntx->conn_state.db_index, GetCurrentTimeMs()};
do {
ess->Await(sid, [&] {
auto cb = [&] {
OpArgs op_args{EngineShard::tlocal(), 0, db_cntx};
OpScan(op_args, scan_opts, &cursor, keys);
});
};
// Avoid deadlocking, if called from shard queue script
if (EngineShard::tlocal() && EngineShard::tlocal()->shard_id() == sid)
cb();
else
ess->Await(sid, cb);
if (cursor == 0) {
++sid;

View File

@ -396,13 +396,13 @@ TEST_F(MultiTest, Eval) {
resp = Run({"eval", "return redis.call('get', 'foo')", "0"});
EXPECT_THAT(resp, "42");
Run({"script", "flush"});
Run({"script", "flush"}); // Reset global flag due to lua_allow_undeclared_auto_correct effect
resp = Run({"eval", "return redis.call('get', 'foo')", "1", "bar"});
EXPECT_THAT(resp, ErrArg("undeclared"));
ASSERT_FALSE(service_->IsLocked(0, "foo"));
Run({"script", "flush"});
Run({"script", "flush"}); // Reset global flag from autocorrect
resp = Run({"eval", "return redis.call('get', 'foo')", "1", "foo"});
EXPECT_THAT(resp, "42");
@ -459,6 +459,11 @@ TEST_F(MultiTest, Eval) {
"1", "foo"}),
"42");
fb.Join();
// Call multi-shard command scan from single shard mode
resp = Run({"eval", "return redis.call('scan', '0'); ", "1", "key"});
EXPECT_EQ(resp.GetVec()[0], "0");
EXPECT_EQ(resp.GetVec()[1].type, RespExpr::Type::ARRAY);
}
#endif