From 2f62f3fbcdbbc839a67bff107cb5d9100580974d Mon Sep 17 00:00:00 2001 From: John Sully Date: Sun, 16 Feb 2020 18:41:29 -0500 Subject: [PATCH 1/2] Fix memory leak in RDB load Former-commit-id: 06ad1c15d719a34fed36244b12a593f749bbb8a6 --- src/rdb.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/rdb.cpp b/src/rdb.cpp index 48205f430..5b316a4a8 100644 --- a/src/rdb.cpp +++ b/src/rdb.cpp @@ -1545,9 +1545,15 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, robj *key, uint64_t mvcc_tstamp) { == NULL) return NULL; if (rdbtype == RDB_TYPE_ZSET_2) { - if (rdbLoadBinaryDoubleValue(rdb,&score) == -1) return NULL; + if (rdbLoadBinaryDoubleValue(rdb,&score) == -1) { + sdsfree(sdsele); + return NULL; + } } else { - if (rdbLoadDoubleValue(rdb,&score) == -1) return NULL; + if (rdbLoadDoubleValue(rdb,&score) == -1) { + sdsfree(sdsele); + return NULL; + } } /* Don't care about integer-encoded strings. */ @@ -2181,6 +2187,8 @@ int rdbLoadRio(rio *rdb, rdbSaveInfo *rsi, int loading_aof) { decrRefCount(val); val = nullptr; } + decrRefCount(key); + key = nullptr; } /* Reset the state that is key-specified and is populated by From 4d01660331f477d280bc54ad3bf5edb09b1521e2 Mon Sep 17 00:00:00 2001 From: John Sully Date: Sun, 16 Feb 2020 18:53:46 -0500 Subject: [PATCH 2/2] Graceful shutdown of server threads when quit is requested Former-commit-id: b9db899f6ccea62222170c6eec264d403a7a911d --- src/db.cpp | 2 +- src/server.cpp | 25 ++++++++++++++++++++++--- src/server.h | 3 +++ 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/db.cpp b/src/db.cpp index e94e0cdb1..562485941 100644 --- a/src/db.cpp +++ b/src/db.cpp @@ -977,7 +977,7 @@ void shutdownCommand(client *c) { * Also when in Sentinel mode clear the SAVE flag and force NOSAVE. */ if (g_pserver->loading || g_pserver->sentinel_mode) flags = (flags & ~SHUTDOWN_SAVE) | SHUTDOWN_NOSAVE; - if (prepareForShutdown(flags) == C_OK) exit(0); + if (prepareForShutdown(flags) == C_OK) throw ShutdownException(); addReplyError(c,"Errors trying to SHUTDOWN. Check logs."); } diff --git a/src/server.cpp b/src/server.cpp index 15f52ab52..6fee88732 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1894,7 +1894,7 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) { /* We received a SIGTERM, shutting down here in a safe way, as it is * not ok doing so inside the signal handler. */ if (g_pserver->shutdown_asap) { - if (prepareForShutdown(SHUTDOWN_NOFLAGS) == C_OK) exit(0); + if (prepareForShutdown(SHUTDOWN_NOFLAGS) == C_OK) throw ShutdownException(); serverLog(LL_WARNING,"SIGTERM received but errors trying to shut down the server, check the logs for more information"); g_pserver->shutdown_asap = 0; } @@ -3812,8 +3812,17 @@ int prepareForShutdown(int flags) { /* Close the listening sockets. Apparently this allows faster restarts. */ closeListeningSockets(1); + + for (int iel = 0; iel < cserver.cthreads; ++iel) + { + aePostFunction(g_pserver->rgthreadvar[iel].el, [iel]{ + g_pserver->rgthreadvar[iel].el->stop = 1; + }); + } + serverLog(LL_WARNING,"%s is now ready to exit, bye bye...", g_pserver->sentinel_mode ? "Sentinel" : "KeyDB"); + return C_OK; } @@ -5033,8 +5042,16 @@ void *workerThreadMain(void *parg) aeEventLoop *el = g_pserver->rgthreadvar[iel].el; aeSetBeforeSleepProc(el, isMainThread ? beforeSleep : beforeSleepLite, isMainThread ? 0 : AE_SLEEP_THREADSAFE); aeSetAfterSleepProc(el, afterSleep, AE_SLEEP_THREADSAFE); - aeMain(el); + try + { + aeMain(el); + } + catch (ShutdownException) + { + } + serverAssert(!GlobalLocksAcquired()); aeDeleteEventLoop(el); + return NULL; } @@ -5334,7 +5351,9 @@ int main(int argc, char **argv) { /* The main thread sleeps until all the workers are done. this is so that all worker threads are orthogonal in their startup/shutdown */ void *pvRet; - pthread_join(rgthread[IDX_EVENT_LOOP_MAIN], &pvRet); + for (int iel = 0; iel < cserver.cthreads; ++iel) + pthread_join(rgthread[iel], &pvRet); + return 0; } diff --git a/src/server.h b/src/server.h index 135a216ae..58ea3e620 100644 --- a/src/server.h +++ b/src/server.h @@ -2922,6 +2922,9 @@ inline int FCorrectThread(client *c) } #define AssertCorrectThread(c) serverAssert(FCorrectThread(c)) +class ShutdownException +{}; + #define redisDebug(fmt, ...) \ printf("DEBUG %s:%d > " fmt "\n", __FILE__, __LINE__, __VA_ARGS__) #define redisDebugMark() \