Modules hooks: do not re-enter in hooks.

Calling a module hook callback may result in callback operations in turn
triggering other events the module is subscribed too. We don't want to
trigger those, it's unsafe and quite confusing, and to do it correcly we
would need to maintain an event list: quite a more complex
implementation.
This commit is contained in:
antirez 2019-10-23 10:47:39 +02:00
parent 89af7e4c85
commit 83de18805c

View File

@ -61,6 +61,7 @@ struct RedisModule {
list *using; /* List of modules we use some APIs of. */
list *filters; /* List of filters the module has registered. */
int in_call; /* RM_Call() nesting level */
int in_hook; /* Non zero if an hook callback is active. */
int options; /* Module options and capabilities. */
RedisModuleInfoFunc info_cb; /* Callback for module to add INFO fields. */
};
@ -817,6 +818,7 @@ void RM_SetModuleAttribs(RedisModuleCtx *ctx, const char *name, int ver, int api
module->using = listCreate();
module->filters = listCreate();
module->in_call = 0;
module->in_hook = 0;
ctx->module = module;
}
@ -5859,7 +5861,7 @@ void moduleFireServerEvent(uint64_t eid, int subid, void *data) {
listRewind(RedisModule_EventListeners,&li);
while((ln = listNext(&li))) {
RedisModuleEventListener *el = ln->value;
if (el->event.id == eid) {
if (el->event.id == eid && !el->module->in_hook) {
RedisModuleCtx ctx = REDISMODULE_CTX_INIT;
ctx.module = el->module;
ctx.client = moduleFreeContextReusedClient;
@ -5876,7 +5878,9 @@ void moduleFireServerEvent(uint64_t eid, int subid, void *data) {
if (fi->dbnum != -1)
selectDb(ctx.client, fi->dbnum);
}
el->module->in_hook = 1;
el->callback(&ctx,el->event,subid,moduledata);
el->module->in_hook = 0;
moduleFreeContext(&ctx);
}
}