Added safety net preventing redis from crashing if a module decide to block in MULTI

This commit is contained in:
Dvir Volk 2017-09-27 15:17:53 +03:00
parent b246635d6d
commit 7393fd814e

View File

@ -3401,14 +3401,16 @@ void unblockClientFromModule(client *c) {
RedisModuleBlockedClient *RM_BlockClient(RedisModuleCtx *ctx, RedisModuleCmdFunc reply_callback, RedisModuleCmdFunc timeout_callback, void (*free_privdata)(void*), long long timeout_ms) { RedisModuleBlockedClient *RM_BlockClient(RedisModuleCtx *ctx, RedisModuleCmdFunc reply_callback, RedisModuleCmdFunc timeout_callback, void (*free_privdata)(void*), long long timeout_ms) {
client *c = ctx->client; client *c = ctx->client;
int islua = c->flags & CLIENT_LUA; int islua = c->flags & CLIENT_LUA;
int ismulti = c->flags & CLIENT_MULTI;
c->bpop.module_blocked_handle = zmalloc(sizeof(RedisModuleBlockedClient)); c->bpop.module_blocked_handle = zmalloc(sizeof(RedisModuleBlockedClient));
RedisModuleBlockedClient *bc = c->bpop.module_blocked_handle; RedisModuleBlockedClient *bc = c->bpop.module_blocked_handle;
/* We need to handle the invalid operation of calling modules blocking /* We need to handle the invalid operation of calling modules blocking
* commands from Lua. We actually create an already aborted (client set to * commands from Lua or MULTI. We actually create an already aborted
* NULL) blocked client handle, and actually reply to Lua with an error. */ * (client set to NULL) blocked client handle, and actually reply with
bc->client = islua ? NULL : c; * an error. */
bc->client = (islua || ismulti) ? NULL : c;
bc->module = ctx->module; bc->module = ctx->module;
bc->reply_callback = reply_callback; bc->reply_callback = reply_callback;
bc->timeout_callback = timeout_callback; bc->timeout_callback = timeout_callback;
@ -3419,9 +3421,10 @@ RedisModuleBlockedClient *RM_BlockClient(RedisModuleCtx *ctx, RedisModuleCmdFunc
bc->dbid = c->db->id; bc->dbid = c->db->id;
c->bpop.timeout = timeout_ms ? (mstime()+timeout_ms) : 0; c->bpop.timeout = timeout_ms ? (mstime()+timeout_ms) : 0;
if (islua) { if (islua || ismulti) {
c->bpop.module_blocked_handle = NULL; c->bpop.module_blocked_handle = NULL;
addReplyError(c,"Blocking module command called from Lua script"); addReplyError(c, islua ? "Blocking module command called from Lua script" :
"Blocking module command called from transaction");
} else { } else {
blockClient(c,BLOCKED_MODULE); blockClient(c,BLOCKED_MODULE);
} }