X-Git-Url: https://git.saurik.com/redis.git/blobdiff_plain/4b8c966140df6df57c47b9a81f7d9f20f8aef34e..f2f2ba1b3ab5147684143ebfb2981c14c9a0bd27:/src/redis.c diff --git a/src/redis.c b/src/redis.c index a387b295..f1fda57b 100644 --- a/src/redis.c +++ b/src/redis.c @@ -62,6 +62,9 @@ double R_Zero, R_PosInf, R_NegInf, R_Nan; /*================================= Globals ================================= */ +/* Alternate stack for SIGSEGV/etc handlers */ +char altstack[SIGSTKSZ]; + /* Global vars */ struct redisServer server; /* server global state */ struct redisCommand *commandTable; @@ -315,14 +318,15 @@ void redisLogFromHandler(int level, const char *msg) { 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); } @@ -353,6 +357,18 @@ long long mstime(void) { 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 @@ -1046,6 +1062,7 @@ void initServerConfig() { 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; @@ -1832,14 +1849,16 @@ sds genRedisInfoString(char *section) { "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, @@ -2023,7 +2042,7 @@ sds genRedisInfoString(char *section) { } } - /* Clusetr */ + /* Cluster */ if (allsections || defsections || !strcasecmp(section,"cluster")) { if (sections++) info = sdscat(info,"\r\n"); info = sdscatprintf(info, @@ -2329,15 +2348,24 @@ static void sigtermHandler(int sig) { 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;