/*================================= Globals ================================= */
+/* Alternate stack for SIGSEGV/etc handlers */
+char altstack[SIGSTKSZ];
+
/* Global vars */
struct redisServer server; /* server global state */
struct redisCommand *commandTable;
STDOUT_FILENO;
if (fd == -1) return;
ll2string(buf,sizeof(buf),getpid());
- write(fd,"[",1);
- write(fd,buf,strlen(buf));
- write(fd," | signal handler] (",20);
+ if (write(fd,"[",1) == -1) goto err;
+ if (write(fd,buf,strlen(buf)) == -1) goto err;
+ if (write(fd," | signal handler] (",20) == -1) goto err;
ll2string(buf,sizeof(buf),time(NULL));
- write(fd,buf,strlen(buf));
- write(fd,") ",2);
- write(fd,msg,strlen(msg));
- write(fd,"\n",1);
+ if (write(fd,buf,strlen(buf)) == -1) goto err;
+ if (write(fd,") ",2) == -1) goto err;
+ if (write(fd,msg,strlen(msg)) == -1) goto err;
+ if (write(fd,"\n",1) == -1) goto err;
+err:
if (server.logfile) close(fd);
}
return ustime()/1000;
}
+/* After an RDB dump or AOF rewrite we exit from children using _exit() instead of
+ * exit(), because the latter may interact with the same file objects used by
+ * the parent process. However if we are testing the coverage normal exit() is
+ * used in order to obtain the right coverage information. */
+void exitFromChild(int retcode) {
+#ifdef COVERAGE_TEST
+ exit(retcode);
+#else
+ _exit(retcode);
+#endif
+}
+
/*====================== Hash table type implementation ==================== */
/* This is an hash table type that uses the SDS dynamic strings libary as
server.aof_filename = zstrdup("appendonly.aof");
server.requirepass = NULL;
server.rdb_compression = 1;
+ server.rdb_checksum = 1;
server.activerehashing = 1;
server.maxclients = REDIS_MAX_CLIENTS;
server.bpop_blocked_clients = 0;
server.lua_time_limit = REDIS_LUA_TIME_LIMIT;
server.lua_client = NULL;
server.lua_timedout = 0;
+ server.lua_protect_globals = 1;
updateLRUClock();
resetServerSaveParams();
server.repl_syncio_timeout = REDIS_REPL_SYNCIO_TIMEOUT;
server.repl_serve_stale_data = 1;
server.repl_slave_ro = 1;
- server.repl_down_since = -1;
+ server.repl_down_since = time(NULL);
/* Client output buffer limits */
server.client_obuf_limits[REDIS_CLIENT_LIMIT_CLASS_NORMAL].hard_limit_bytes = 0;
"bgsave_in_progress:%d\r\n"
"last_save_time:%ld\r\n"
"last_bgsave_status:%s\r\n"
- "bgrewriteaof_in_progress:%d\r\n",
+ "bgrewriteaof_in_progress:%d\r\n"
+ "bgrewriteaof_scheduled:%d\r\n",
server.loading,
server.aof_state != REDIS_AOF_OFF,
server.dirty,
server.rdb_child_pid != -1,
server.lastsave,
server.lastbgsave_status == REDIS_OK ? "ok" : "err",
- server.aof_child_pid != -1);
+ server.aof_child_pid != -1,
+ server.aof_rewrite_scheduled);
if (server.aof_state != REDIS_AOF_OFF) {
info = sdscatprintf(info,
}
void version() {
- printf("Redis server v=%s sha=%s:%d malloc=%s\n", REDIS_VERSION,
- redisGitSHA1(), atoi(redisGitDirty()) > 0, ZMALLOC_LIB);
+ printf("Redis server v=%s sha=%s:%d malloc=%s bits=%d\n",
+ REDIS_VERSION,
+ redisGitSHA1(),
+ atoi(redisGitDirty()) > 0,
+ ZMALLOC_LIB,
+ sizeof(long) == 4 ? 32 : 64);
exit(0);
}
void setupSignalHandlers(void) {
struct sigaction act;
+ stack_t stack;
+
+ stack.ss_sp = altstack;
+ stack.ss_flags = 0;
+ stack.ss_size = SIGSTKSZ;
+
+ sigaltstack(&stack, NULL);
/* When the SA_SIGINFO flag is set in sa_flags then sa_sigaction is used.
* Otherwise, sa_handler is used. */
sigemptyset(&act.sa_mask);
- act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND;
+ act.sa_flags = 0;
act.sa_handler = sigtermHandler;
sigaction(SIGTERM, &act, NULL);
#ifdef HAVE_BACKTRACE
+ /* Use alternate stack so we don't clobber stack in case of segv, or when we run out of stack ..
+ * also resethand & nodefer so we can get interrupted (and killed) if we cause SEGV during SEGV handler */
sigemptyset(&act.sa_mask);
act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO;
act.sa_sigaction = sigsegvHandler;