Redis 2.6.8
This commit is contained in:
@@ -14,6 +14,17 @@ HIGH: There is a critical bug that may affect a subset of users. Upgrade!
|
||||
CRITICAL: There is a critical bug affecting MOST USERS. Upgrade ASAP.
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
--[ Redis 2.6.8 ]
|
||||
|
||||
UPGRADE URGENCY: MODERATE if you use Lua scripting. Otherwise LOW.
|
||||
|
||||
* [BUGFIX] Multiple fixes for EVAL (issue #872).
|
||||
* [BUGFIX] Fix overflow in mstime() in redis-cli and benchmark.
|
||||
* [BUGFIX] Fix Linux / PPC64 behavior by correcting endianess detection.
|
||||
* [BUGFIX] Fix NetBSD build by defining _XOPEN_SOURCE appropriately.
|
||||
* [BUGFIX] Added missing license and copyright in a few places.
|
||||
* [BUGFIX] Better error reporting when fd event creation fails.
|
||||
|
||||
--[ Redis 2.6.7 ]
|
||||
|
||||
UPGRADE URGENCY: MODERATE (unless you BLPOP using the same key multiple times).
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <poll.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "ae.h"
|
||||
#include "zmalloc.h"
|
||||
@@ -104,7 +105,10 @@ void aeStop(aeEventLoop *eventLoop) {
|
||||
int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask,
|
||||
aeFileProc *proc, void *clientData)
|
||||
{
|
||||
if (fd >= eventLoop->setsize) return AE_ERR;
|
||||
if (fd >= eventLoop->setsize) {
|
||||
errno = ERANGE;
|
||||
return AE_ERR;
|
||||
}
|
||||
aeFileEvent *fe = &eventLoop->events[fd];
|
||||
|
||||
if (aeApiAddEvent(eventLoop, fd, mask) == -1)
|
||||
|
||||
+3
-1
@@ -517,7 +517,9 @@ void copyClientOutputBuffer(redisClient *dst, redisClient *src) {
|
||||
static void acceptCommonHandler(int fd, int flags) {
|
||||
redisClient *c;
|
||||
if ((c = createClient(fd)) == NULL) {
|
||||
redisLog(REDIS_WARNING,"Error allocating resources for the client");
|
||||
redisLog(REDIS_WARNING,
|
||||
"Error registering fd event for the new client: %s (fd=%d)",
|
||||
strerror(errno),fd);
|
||||
close(fd); /* May be already closed, just ignore errors */
|
||||
return;
|
||||
}
|
||||
|
||||
+3
-2
@@ -1528,8 +1528,9 @@ void call(redisClient *c, int flags) {
|
||||
if (flags != REDIS_PROPAGATE_NONE)
|
||||
propagate(c->cmd,c->db->id,c->argv,c->argc,flags);
|
||||
}
|
||||
/* Commands such as LPUSH or BRPOPLPUSH may propagate an additional
|
||||
* PUSH command. */
|
||||
|
||||
/* Handle the alsoPropagate() API to handle commands that want to propagate
|
||||
* multiple separated commands. */
|
||||
if (server.also_propagate.numops) {
|
||||
int j;
|
||||
redisOp *rop;
|
||||
|
||||
+3
-1
@@ -636,7 +636,9 @@ void syncWithMaster(aeEventLoop *el, int fd, void *privdata, int mask) {
|
||||
if (aeCreateFileEvent(server.el,fd, AE_READABLE,readSyncBulkPayload,NULL)
|
||||
== AE_ERR)
|
||||
{
|
||||
redisLog(REDIS_WARNING,"Can't create readable event for SYNC");
|
||||
redisLog(REDIS_WARNING,
|
||||
"Can't create readable event for SYNC: %s (fd=%d)",
|
||||
strerror(errno),fd);
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
||||
+21
-20
@@ -787,7 +787,7 @@ void evalGenericCommand(redisClient *c, int evalsha) {
|
||||
lua_State *lua = server.lua;
|
||||
char funcname[43];
|
||||
long long numkeys;
|
||||
int delhook = 0;
|
||||
int delhook = 0, err;
|
||||
|
||||
/* We want the same PRNG sequence at every call so that our PRNG is
|
||||
* not affected by external state. */
|
||||
@@ -869,30 +869,31 @@ void evalGenericCommand(redisClient *c, int evalsha) {
|
||||
/* At this point whatever this script was never seen before or if it was
|
||||
* already defined, we can call it. We have zero arguments and expect
|
||||
* a single return value. */
|
||||
if (lua_pcall(lua,0,1,0)) {
|
||||
if (delhook) lua_sethook(lua,luaMaskCountHook,0,0); /* Disable hook */
|
||||
if (server.lua_timedout) {
|
||||
server.lua_timedout = 0;
|
||||
/* Restore the readable handler that was unregistered when the
|
||||
* script timeout was detected. */
|
||||
aeCreateFileEvent(server.el,c->fd,AE_READABLE,
|
||||
readQueryFromClient,c);
|
||||
}
|
||||
server.lua_caller = NULL;
|
||||
selectDb(c,server.lua_client->db->id); /* set DB ID from Lua client */
|
||||
addReplyErrorFormat(c,"Error running script (call to %s): %s\n",
|
||||
funcname, lua_tostring(lua,-1));
|
||||
lua_pop(lua,1);
|
||||
lua_gc(lua,LUA_GCCOLLECT,0);
|
||||
return;
|
||||
}
|
||||
err = lua_pcall(lua,0,1,0);
|
||||
|
||||
/* Perform some cleanup that we need to do both on error and success. */
|
||||
if (delhook) lua_sethook(lua,luaMaskCountHook,0,0); /* Disable hook */
|
||||
server.lua_timedout = 0;
|
||||
if (server.lua_timedout) {
|
||||
server.lua_timedout = 0;
|
||||
/* Restore the readable handler that was unregistered when the
|
||||
* script timeout was detected. */
|
||||
aeCreateFileEvent(server.el,c->fd,AE_READABLE,
|
||||
readQueryFromClient,c);
|
||||
}
|
||||
server.lua_caller = NULL;
|
||||
selectDb(c,server.lua_client->db->id); /* set DB ID from Lua client */
|
||||
luaReplyToRedisReply(c,lua);
|
||||
lua_gc(lua,LUA_GCSTEP,1);
|
||||
|
||||
if (err) {
|
||||
addReplyErrorFormat(c,"Error running script (call to %s): %s\n",
|
||||
funcname, lua_tostring(lua,-1));
|
||||
lua_pop(lua,1); /* Consume the Lua reply. */
|
||||
} else {
|
||||
/* On success convert the Lua return value into Redis protocol, and
|
||||
* send it to * the client. */
|
||||
luaReplyToRedisReply(c,lua);
|
||||
}
|
||||
|
||||
/* If we have slaves attached we want to replicate this command as
|
||||
* EVAL instead of EVALSHA. We do this also in the AOF as currently there
|
||||
* is no easy way to propagate a command in a different way in the AOF
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
#define REDIS_VERSION "2.6.7"
|
||||
#define REDIS_VERSION "2.6.8"
|
||||
|
||||
@@ -297,6 +297,12 @@ start_server {tags {"scripting"}} {
|
||||
assert_equal [r ping] "PONG"
|
||||
}
|
||||
|
||||
test {Timedout script link is still usable after Lua returns} {
|
||||
r config set lua-time-limit 10
|
||||
r eval {for i=1,100000 do redis.call('ping') end return 'ok'} 0
|
||||
r ping
|
||||
} {PONG}
|
||||
|
||||
test {Timedout scripts that modified data can't be killed by SCRIPT KILL} {
|
||||
set rd [redis_deferring_client]
|
||||
r config set lua-time-limit 10
|
||||
@@ -310,6 +316,8 @@ start_server {tags {"scripting"}} {
|
||||
assert_match {BUSY*} $e
|
||||
}
|
||||
|
||||
# Note: keep this test at the end of this server stanza because it
|
||||
# kills the server.
|
||||
test {SHUTDOWN NOSAVE can kill a timedout script anyway} {
|
||||
# The server sould be still unresponding to normal commands.
|
||||
catch {r ping} e
|
||||
@@ -323,9 +331,16 @@ start_server {tags {"scripting"}} {
|
||||
|
||||
start_server {tags {"scripting repl"}} {
|
||||
start_server {} {
|
||||
test {Before the slave connects we issue an EVAL command} {
|
||||
test {Before the slave connects we issue two EVAL commands} {
|
||||
# One with an error, but still executing a command.
|
||||
# SHA is: 6e8bd6bdccbe78899e3cc06b31b6dbf4324c2e56
|
||||
catch {
|
||||
r eval {redis.call('incr','x'); redis.call('nonexisting')} 0
|
||||
}
|
||||
# One command is correct:
|
||||
# SHA is: ae3477e27be955de7e1bc9adfdca626b478d3cb2
|
||||
r eval {return redis.call('incr','x')} 0
|
||||
} {1}
|
||||
} {2}
|
||||
|
||||
test {Connect a slave to the main instance} {
|
||||
r -1 slaveof [srv 0 host] [srv 0 port]
|
||||
@@ -337,15 +352,20 @@ start_server {tags {"scripting repl"}} {
|
||||
}
|
||||
}
|
||||
|
||||
test {Now use EVALSHA against the master} {
|
||||
test {Now use EVALSHA against the master, with both SHAs} {
|
||||
# The server should replicate successful and unsuccessful
|
||||
# commands as EVAL instead of EVALSHA.
|
||||
catch {
|
||||
r evalsha 6e8bd6bdccbe78899e3cc06b31b6dbf4324c2e56 0
|
||||
}
|
||||
r evalsha ae3477e27be955de7e1bc9adfdca626b478d3cb2 0
|
||||
} {2}
|
||||
} {4}
|
||||
|
||||
test {If EVALSHA was replicated as EVAL the slave should be ok} {
|
||||
test {If EVALSHA was replicated as EVAL, 'x' should be '4'} {
|
||||
wait_for_condition 50 100 {
|
||||
[r -1 get x] eq {2}
|
||||
[r -1 get x] eq {4}
|
||||
} else {
|
||||
fail "Expected 2 in x, but value is '[r -1 get x]'"
|
||||
fail "Expected 4 in x, but value is '[r -1 get x]'"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user