int daemonize;
int appendonly;
int appendfsync;
+ int shutdown_asap;
time_t lastfsync;
int appendfd;
int appendseldb;
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);
* 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;
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();
}
/*================================== 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
/* 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,
* 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 =============================== */
}
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) {
_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) {
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;
}