From 919580a2282d2cccbfd010c7171956dd2eae77c4 Mon Sep 17 00:00:00 2001 From: Yossi Gottlieb Date: Tue, 18 Aug 2020 17:16:08 +0300 Subject: [PATCH] Modules: expose real client on conn events. When REDISMODULE_EVENT_CLIENT_CHANGE events are delivered, modules may want to mutate the client state (e.g. perform authentication). This change links the module context with the real client rather than a fake client for these events. (cherry picked from commit 67b43f75e23ba7a3915bc87e7edaa306fd1eee65) --- src/module.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/module.c b/src/module.c index 65d22b713..afb525dbe 100644 --- a/src/module.c +++ b/src/module.c @@ -7263,6 +7263,7 @@ void moduleFireServerEvent(uint64_t eid, int subid, void *data) { * cheap if there are no registered modules. */ if (listLength(RedisModule_EventListeners) == 0) return; + int real_client_used = 0; listIter li; listNode *ln; listRewind(RedisModule_EventListeners,&li); @@ -7272,7 +7273,15 @@ void moduleFireServerEvent(uint64_t eid, int subid, void *data) { RedisModuleCtx ctx = REDISMODULE_CTX_INIT; ctx.module = el->module; - if (ModulesInHooks == 0) { + if (eid == REDISMODULE_EVENT_CLIENT_CHANGE) { + /* In the case of client changes, we're pushing the real client + * so the event handler can mutate it if needed. For example, + * to change its authentication state in a way that does not + * depend on specific commands executed later. + */ + ctx.client = (client *) data; + real_client_used = 1; + } else if (ModulesInHooks == 0) { ctx.client = moduleFreeContextReusedClient; } else { ctx.client = createClient(NULL); @@ -7325,7 +7334,7 @@ void moduleFireServerEvent(uint64_t eid, int subid, void *data) { el->module->in_hook--; ModulesInHooks--; - if (ModulesInHooks != 0) freeClient(ctx.client); + if (ModulesInHooks != 0 && !real_client_used) freeClient(ctx.client); moduleFreeContext(&ctx); } }