Return errors if a write command is called inside a Lua script after a random command was called. See https://github.com/antirez/redis/issues/95 for more information.

This commit is contained in:
antirez 2011-09-27 15:30:31 +02:00
parent 15ef605340
commit 9f772cc237
2 changed files with 20 additions and 0 deletions

View File

@ -623,6 +623,8 @@ struct redisServer {
dict *lua_scripts; /* A dictionary of SHA1 -> Lua scripts */
long long lua_time_limit;
long long lua_time_start;
int lua_random_dirty; /* True if a random command was called during the
exection of the current script. */
};
typedef struct pubsubPattern {

View File

@ -180,6 +180,14 @@ int luaRedisCommand(lua_State *lua) {
goto cleanup;
}
if (cmd->flags & REDIS_CMD_WRITE && server.lua_random_dirty) {
luaPushError(lua,
"Write commands not allowed after non deterministic commands");
goto cleanup;
}
if (cmd->flags & REDIS_CMD_RANDOM) server.lua_random_dirty = 1;
/* Run the command */
cmd->proc(c);
@ -425,6 +433,16 @@ void evalGenericCommand(redisClient *c, int evalsha) {
* not affected by external state. */
redisSrand48(0);
/* We set this flag to zero to remember that so far no random command
* was called. This way we can allow the user to call commands like
* SRANDMEMBER or RANDOMKEY from Lua scripts as far as no write command
* is called (otherwise the replication and AOF would end with non
* deterministic sequences).
*
* Thanks to this flag we'll raise an error every time a write command
* is called after a random command was used. */
server.lua_random_dirty = 0;
/* Get the number of arguments that are keys */
if (getLongLongFromObjectOrReply(c,c->argv[2],&numkeys,NULL) != REDIS_OK)
return;