summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorOran Agra <oran@redislabs.com>2022-04-18 14:56:00 +0300
committerGitHub <noreply@github.com>2022-04-18 14:56:00 +0300
commit7d1ad6ca9663e3f771d1f27eec3ab67d0a1b6faf (patch)
treec1f5e7b0e17fe5959e2e6a8cbc4ff8c64e493117 /src
parentfe4b4806b3f39256a82020a1cd2e832ebabc2ef9 (diff)
downloadredis-7d1ad6ca9663e3f771d1f27eec3ab67d0a1b6faf.tar.gz
Fix RM_Yield bug processing future commands of the current client. (#10573)
RM_Yield was missing a call to protectClient to prevent redis from processing future commands of the yielding client. Adding tests that fail without this fix. This would be complicated to solve since nested calls to RM_Call used to replace the current_client variable with the module temp client. It looks like it's no longer necessary to do that, since it was added back in #9890 to solve two issues, both already gone: 1. call to CONFIG SET maxmemory could trigger a module hook calling RM_Call. although this specific issue is gone, arguably other hooks like keyspace notification, can do the same. 2. an assertion in lookupKey that checks the current command of the current client, introduced in #9572 and removed in #10248
Diffstat (limited to 'src')
-rw-r--r--src/module.c12
1 files changed, 7 insertions, 5 deletions
diff --git a/src/module.c b/src/module.c
index 04a5be721..288e0795f 100644
--- a/src/module.c
+++ b/src/module.c
@@ -717,6 +717,8 @@ void moduleFreeContext(RedisModuleCtx *ctx) {
if (server.busy_module_yield_flags) {
blockingOperationEnds();
server.busy_module_yield_flags = BUSY_MODULE_YIELD_NONE;
+ if (server.current_client)
+ unprotectClient(server.current_client);
unblockPostponedClients();
}
}
@@ -2108,6 +2110,8 @@ void RM_Yield(RedisModuleCtx *ctx, int flags, const char *busy_reply) {
if (!server.busy_module_yield_flags) {
server.busy_module_yield_flags = BUSY_MODULE_YIELD_EVENTS;
blockingOperationStarts();
+ if (server.current_client)
+ protectClient(server.current_client);
}
if (flags & REDISMODULE_YIELD_FLAG_CLIENTS)
server.busy_module_yield_flags |= BUSY_MODULE_YIELD_CLIENTS;
@@ -2125,7 +2129,7 @@ void RM_Yield(RedisModuleCtx *ctx, int flags, const char *busy_reply) {
/* decide when the next event should fire. */
ctx->next_yield_time = now + 1000000 / server.hz;
}
- yield_nesting --;
+ yield_nesting--;
}
/* Set flags defining capabilities or behavior bit flags.
@@ -5909,11 +5913,7 @@ RedisModuleCallReply *RM_Call(RedisModuleCtx *ctx, const char *cmdname, const ch
if (!(flags & REDISMODULE_ARGV_NO_REPLICAS))
call_flags |= CMD_CALL_PROPAGATE_REPL;
}
- /* Set server.current_client */
- client *old_client = server.current_client;
- server.current_client = c;
call(c,call_flags);
- server.current_client = old_client;
server.replication_allowed = prev_replication_allowed;
serverAssert((c->flags & CLIENT_BLOCKED) == 0);
@@ -7650,6 +7650,8 @@ void moduleGILBeforeUnlock() {
if (server.busy_module_yield_flags) {
blockingOperationEnds();
server.busy_module_yield_flags = BUSY_MODULE_YIELD_NONE;
+ if (server.current_client)
+ unprotectClient(server.current_client);
unblockPostponedClients();
}
}