X-Git-Url: https://git.saurik.com/redis.git/blobdiff_plain/c14753cea16cc963363b0d3002dc94b33c1f2075..7fc98533392f455974d546c88bd4d41c85e6fe6d:/redis.c?ds=sidebyside diff --git a/redis.c b/redis.c index 97b0c5c9..dc8d84ff 100644 --- a/redis.c +++ b/redis.c @@ -27,7 +27,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#define REDIS_VERSION "1.3.12" +#define REDIS_VERSION "1.3.14" #include "fmacros.h" #include "config.h" @@ -366,6 +366,7 @@ struct redisServer { int daemonize; int appendonly; int appendfsync; + int shutdown_asap; time_t lastfsync; int appendfd; int appendseldb; @@ -631,6 +632,7 @@ static int equalStringObjects(robj *a, robj *b); static void usage(); static int rewriteAppendOnlyFileBackground(void); static int vmSwapObjectBlocking(robj *key, robj *val); +static int prepareForShutdown(); static void authCommand(redisClient *c); static void pingCommand(redisClient *c); @@ -1420,6 +1422,13 @@ static int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientD * To access a global var is faster than calling time(NULL) */ server.unixtime = time(NULL); + /* We received a SIGTERM, shutting down here in a safe way, as it is + * not ok doing so inside the signal handler. */ + if (server.shutdown_asap) { + if (prepareForShutdown() == REDIS_OK) exit(0); + redisLog(REDIS_WARNING,"SIGTERM received but errors trying to shut down the server, check the logs for more information"); + } + /* Show some info about non-empty databases */ for (j = 0; j < server.dbnum; j++) { long long size, used, vkeys; @@ -1687,6 +1696,7 @@ static void initServerConfig() { server.vm_blocked_clients = 0; server.hash_max_zipmap_entries = REDIS_HASH_MAX_ZIPMAP_ENTRIES; server.hash_max_zipmap_value = REDIS_HASH_MAX_ZIPMAP_VALUE; + server.shutdown_asap = 0; resetServerSaveParams(); @@ -2917,8 +2927,8 @@ static robj *createStringObjectFromLongLong(long long value) { incrRefCount(shared.integers[value]); o = shared.integers[value]; } else { - o = createObject(REDIS_STRING, NULL); if (value >= LONG_MIN && value <= LONG_MAX) { + o = createObject(REDIS_STRING, NULL); o->encoding = REDIS_ENCODING_INT; o->ptr = (void*)((long)value); } else { @@ -4150,7 +4160,7 @@ eoferr: /* unexpected end of file is handled here with a fatal exit */ } /*================================== Shutdown =============================== */ -static void redisShutdown() { +static int prepareForShutdown() { redisLog(REDIS_WARNING,"User requested shutdown, saving DB..."); /* Kill the saving child if there is a background saving in progress. We want to avoid race conditions, for instance our saving child may @@ -4164,15 +4174,12 @@ static void redisShutdown() { /* Append only file: fsync() the AOF and exit */ fsync(server.appendfd); if (server.vm_enabled) unlink(server.vm_swap_file); - exit(0); } else { /* Snapshotting. Perform a SYNC SAVE and exit */ if (rdbSave(server.dbfilename) == REDIS_OK) { if (server.daemonize) unlink(server.pidfile); redisLog(REDIS_WARNING,"%zu bytes used at exit",zmalloc_used_memory()); - redisLog(REDIS_WARNING,"Server exit now, bye bye..."); - exit(0); } else { /* Ooops.. error saving! The best we can do is to continue * operating. Note that if there was a background saving process, @@ -4180,8 +4187,11 @@ static void redisShutdown() { * saving aborted, handling special stuff like slaves pending for * synchronization... */ redisLog(REDIS_WARNING,"Error trying to save the DB, can't exit"); + return REDIS_ERR; } } + redisLog(REDIS_WARNING,"Server exit now, bye bye..."); + return REDIS_OK; } /*================================== Commands =============================== */ @@ -4623,10 +4633,9 @@ static void bgsaveCommand(redisClient *c) { } static void shutdownCommand(redisClient *c) { - redisShutdown(); - /* If we got here exit was not called so there was an error */ - addReplySds(c, - sdsnew("-ERR can't quit, problems saving the DB\r\n")); + if (prepareForShutdown() == REDIS_OK) + exit(0); + addReplySds(c, sdsnew("-ERR Errors trying to SHUTDOWN. Check logs.\r\n")); } static void renameGenericCommand(redisClient *c, int nx) { @@ -5403,8 +5412,10 @@ static zskiplistNode *zslCreateNode(int level, double score, robj *obj) { zskiplistNode *zn = zmalloc(sizeof(*zn)); zn->forward = zmalloc(sizeof(zskiplistNode*) * level); - if (level > 0) + if (level > 1) zn->span = zmalloc(sizeof(unsigned int) * (level - 1)); + else + zn->span = NULL; zn->score = score; zn->obj = obj; return zn; @@ -10423,18 +10434,23 @@ static void computeDatasetDigest(unsigned char *final) { /* Iterate this DB writing every entry */ while((de = dictNext(di)) != NULL) { - robj *key, *o; + robj *key, *o, *kcopy; time_t expiretime; memset(digest,0,20); /* This key-val digest */ key = dictGetEntryKey(de); - mixObjectDigest(digest,key); - if (!server.vm_enabled || key->storage == REDIS_VM_MEMORY || - key->storage == REDIS_VM_SWAPPING) { + + if (!server.vm_enabled) { + mixObjectDigest(digest,key); o = dictGetEntryVal(de); - incrRefCount(o); } else { - o = vmPreviewObject(key); + /* Don't work with the key directly as when VM is active + * this is unsafe: TODO: fix decrRefCount to check if the + * count really reached 0 to avoid this mess */ + kcopy = dupStringObject(key); + mixObjectDigest(digest,kcopy); + o = lookupKeyRead(db,kcopy); + decrRefCount(kcopy); } aux = htonl(o->type); mixDigest(digest,&aux,sizeof(aux)); @@ -10503,7 +10519,6 @@ static void computeDatasetDigest(unsigned char *final) { } else { redisPanic("Unknown object type"); } - decrRefCount(o); /* If the key has an expire, add it to the mix */ if (expiretime != -1) xorDigest(digest,"!!expire!!",10); /* We can finally xor the key-val digest to the final digest */ @@ -10818,13 +10833,11 @@ static void segvHandler(int sig, siginfo_t *info, void *secret) { _exit(0); } -static void sigHandler(int sig) { - redisLog(REDIS_WARNING, - "======= Redis %s got signal: -%d- =======", REDIS_VERSION, sig); +static void sigtermHandler(int sig) { + REDIS_NOTUSED(sig); - if (sig == SIGTERM) { - redisShutdown(); - } + redisLog(REDIS_WARNING,"SIGTERM received, scheduling shutting down..."); + server.shutdown_asap = 1; } static void setupSigSegvAction(void) { @@ -10842,7 +10855,7 @@ static void setupSigSegvAction(void) { sigaction (SIGBUS, &act, NULL); act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND; - act.sa_handler = sigHandler; + act.sa_handler = sigtermHandler; sigaction (SIGTERM, &act, NULL); return; }