X-Git-Url: https://git.saurik.com/redis.git/blobdiff_plain/81f32c7b65c72a45fe1637ab0a661b144c54eb7c..0f51e3c5640c2f5be2766f10660f668bc71c7dd9:/src/redis.c diff --git a/src/redis.c b/src/redis.c index 39de86af..9c49bc22 100644 --- a/src/redis.c +++ b/src/redis.c @@ -291,6 +291,34 @@ void redisLog(int level, const char *fmt, ...) { redisLogRaw(level,msg); } +/* Log a fixed message without printf-alike capabilities, in a way that is + * safe to call from a signal handler. + * + * We actually use this only for signals that are not fatal from the point + * of view of Redis. Signals that are going to kill the server anyway and + * where we need printf-alike features are served by redisLog(). */ +void redisLogFromHandler(int level, const char *msg) { + int fd; + char buf[64]; + + if ((level&0xff) < server.verbosity || + (server.logfile == NULL && server.daemonize)) return; + fd = server.logfile ? + open(server.logfile, O_APPEND|O_CREAT|O_WRONLY, 0644) : + STDOUT_FILENO; + if (fd == -1) return; + ll2string(buf,sizeof(buf),getpid()); + write(fd,"[",1); + write(fd,buf,strlen(buf)); + write(fd," | signal handler] (",20); + ll2string(buf,sizeof(buf),time(NULL)); + write(fd,buf,strlen(buf)); + write(fd,") ",2); + write(fd,msg,strlen(msg)); + write(fd,"\n",1); + if (server.logfile) close(fd); +} + /* Redis generally does not try to recover from out of memory conditions * when allocating objects or strings, it is not clear if it will be possible * to report this condition to the client since the networking layer itself @@ -599,7 +627,7 @@ void activeExpireCycle(void) { } void updateLRUClock(void) { - server.lruclock = (time(NULL)/REDIS_LRU_CLOCK_RESOLUTION) & + server.lruclock = (server.unixtime/REDIS_LRU_CLOCK_RESOLUTION) & REDIS_LRU_CLOCK_MAX; } @@ -713,6 +741,10 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) { REDIS_NOTUSED(id); REDIS_NOTUSED(clientData); + /* Software watchdog: deliver the SIGALRM that will reach the signal + * handler if we don't return here fast enough. */ + if (server.watchdog_period) watchdogScheduleSignal(server.watchdog_period); + /* We take a cached value of the unix time in the global state because * with virtual memory and aging there is to store the current time * in objects at every object access, and accuracy is not needed. @@ -808,15 +840,13 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) { updateDictResizePolicy(); } } else { - time_t now = time(NULL); - /* If there is not a background saving/rewrite in progress check if * we have to save/rewrite now */ for (j = 0; j < server.saveparamslen; j++) { struct saveparam *sp = server.saveparams+j; if (server.dirty >= sp->changes && - now-server.lastsave > sp->seconds) { + server.unixtime-server.lastsave > sp->seconds) { redisLog(REDIS_NOTICE,"%d changes in %d seconds. Saving...", sp->changes, sp->seconds); rdbSaveBackground(server.rdb_filename); @@ -1068,11 +1098,12 @@ void initServerConfig() { server.slowlog_log_slower_than = REDIS_SLOWLOG_LOG_SLOWER_THAN; server.slowlog_max_len = REDIS_SLOWLOG_MAX_LEN; - /* Assert */ + /* Debugging */ server.assert_failed = ""; server.assert_file = ""; server.assert_line = 0; server.bug_report_start = 0; + server.watchdog_period = 0; } /* This function will try to raise the max number of open files accordingly to @@ -1641,7 +1672,7 @@ void bytesToHuman(char *s, unsigned long long n) { * on memory corruption problems. */ sds genRedisInfoString(char *section) { sds info = sdsempty(); - time_t uptime = time(NULL)-server.stat_starttime; + time_t uptime = server.unixtime-server.stat_starttime; int j, numcommands; struct rusage self_ru, c_ru; unsigned long lol, bib; @@ -1780,7 +1811,7 @@ sds genRedisInfoString(char *section) { perc = ((double)server.loading_loaded_bytes / server.loading_total_bytes) * 100; - elapsed = time(NULL)-server.loading_start_time; + elapsed = server.unixtime-server.loading_start_time; if (elapsed == 0) { eta = 1; /* A fake 1 second figure if we don't have enough info */ @@ -1851,7 +1882,7 @@ sds genRedisInfoString(char *section) { (server.repl_state == REDIS_REPL_CONNECTED) ? "up" : "down", server.master ? - ((int)(time(NULL)-server.master->lastinteraction)) : -1, + ((int)(server.unixtime-server.master->lastinteraction)) : -1, server.repl_state == REDIS_REPL_TRANSFER ); @@ -1860,14 +1891,14 @@ sds genRedisInfoString(char *section) { "master_sync_left_bytes:%ld\r\n" "master_sync_last_io_seconds_ago:%d\r\n" ,(long)server.repl_transfer_left, - (int)(time(NULL)-server.repl_transfer_lastio) + (int)(server.unixtime-server.repl_transfer_lastio) ); } if (server.repl_state != REDIS_REPL_CONNECTED) { info = sdscatprintf(info, "master_link_down_since_seconds:%ld\r\n", - (long)time(NULL)-server.repl_down_since); + (long)server.unixtime-server.repl_down_since); } } info = sdscatprintf(info, @@ -2228,7 +2259,7 @@ void redisAsciiArt(void) { static void sigtermHandler(int sig) { REDIS_NOTUSED(sig); - redisLog(REDIS_WARNING,"Received SIGTERM, scheduling shutdown..."); + redisLogFromHandler(REDIS_WARNING,"Received SIGTERM, scheduling shutdown..."); server.shutdown_asap = 1; }