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); } }