X-Git-Url: https://git.saurik.com/redis.git/blobdiff_plain/68d6345ddf6b0088e25d5f3b5ee93ad51833d5d1..0b10e1044496699585b401196dd86e19a9f87cc4:/src/redis.c diff --git a/src/redis.c b/src/redis.c index e59f3a73..866ac360 100644 --- a/src/redis.c +++ b/src/redis.c @@ -192,24 +192,20 @@ struct redisCommand redisCommandTable[] = { /*============================ Utility functions ============================ */ -void redisLog(int level, const char *fmt, ...) { +/* Low level logging. To use only for very big messages, otherwise + * redisLog() is to prefer. */ +void redisLogRaw(int level, const char *msg) { const int syslogLevelMap[] = { LOG_DEBUG, LOG_INFO, LOG_NOTICE, LOG_WARNING }; const char *c = ".-*#"; time_t now = time(NULL); - va_list ap; FILE *fp; char buf[64]; - char msg[REDIS_MAX_LOGMSG_LEN]; if (level < server.verbosity) return; fp = (server.logfile == NULL) ? stdout : fopen(server.logfile,"a"); if (!fp) return; - va_start(ap, fmt); - vsnprintf(msg, sizeof(msg), fmt, ap); - va_end(ap); - strftime(buf,sizeof(buf),"%d %b %H:%M:%S",localtime(&now)); fprintf(fp,"[%d] %s %c %s\n",(int)getpid(),buf,c[level],msg); fflush(fp); @@ -219,6 +215,22 @@ void redisLog(int level, const char *fmt, ...) { if (server.syslog_enabled) syslog(syslogLevelMap[level], "%s", msg); } +/* Like redisLogRaw() but with printf-alike support. This is the funciton that + * is used across the code. The raw version is only used in order to dump + * the INFO output on crash. */ +void redisLog(int level, const char *fmt, ...) { + va_list ap; + char msg[REDIS_MAX_LOGMSG_LEN]; + + if (level < server.verbosity) return; + + va_start(ap, fmt); + vsnprintf(msg, sizeof(msg), fmt, ap); + va_end(ap); + + redisLogRaw(level,msg); +} + /* 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 @@ -847,7 +859,7 @@ void initServer() { signal(SIGHUP, SIG_IGN); signal(SIGPIPE, SIG_IGN); - setupSigSegvAction(); + setupSignalHandlers(); if (server.syslog_enabled) { openlog(server.syslog_ident, LOG_PID | LOG_NDELAY | LOG_NOWAIT, @@ -865,12 +877,12 @@ void initServer() { server.el = aeCreateEventLoop(); server.db = zmalloc(sizeof(redisDb)*server.dbnum); - if (server.port != 0) + if (server.port != 0) { server.ipfd = anetTcpServer(server.neterr,server.port,server.bindaddr); - - if (server.ipfd == ANET_ERR) { - redisLog(REDIS_WARNING, "Opening port: %s", server.neterr); - exit(1); + if (server.ipfd == ANET_ERR) { + redisLog(REDIS_WARNING, "Opening port: %s", server.neterr); + exit(1); + } } if (server.unixsocket != NULL) { unlink(server.unixsocket); /* don't care if this fails */ @@ -933,6 +945,7 @@ void initServer() { } if (server.ds_enabled) dsInit(); + srand(time(NULL)^getpid()); } /* Populates the Redis Command Table starting from the hard coded list @@ -1334,8 +1347,18 @@ sds genRedisInfoString(char *section) { info = sdscatprintf(info, "cache_max_memory:%llu\r\n" "cache_blocked_clients:%lu\r\n" + "cache_io_queue_len:%lu\r\n" + "cache_io_jobs_new:%lu\r\n" + "cache_io_jobs_processing:%lu\r\n" + "cache_io_jobs_processed:%lu\r\n" + "cache_io_ready_clients:%lu\r\n" ,(unsigned long long) server.cache_max_memory, - (unsigned long) server.cache_blocked_clients + (unsigned long) server.cache_blocked_clients, + (unsigned long) listLength(server.cache_io_queue), + (unsigned long) listLength(server.io_newjobs), + (unsigned long) listLength(server.io_processing), + (unsigned long) listLength(server.io_processed), + (unsigned long) listLength(server.io_ready_clients) ); unlockThreadedIO(); } @@ -1641,7 +1664,7 @@ void usage() { } int main(int argc, char **argv) { - time_t start; + long long start; initServerConfig(); if (argc == 2) { @@ -1662,15 +1685,15 @@ int main(int argc, char **argv) { #ifdef __linux__ linuxOvercommitMemoryWarning(); #endif - start = time(NULL); + start = ustime(); if (server.ds_enabled) { redisLog(REDIS_NOTICE,"DB not loaded (running with disk back end)"); } else if (server.appendonly) { if (loadAppendOnlyFile(server.appendfilename) == REDIS_OK) - redisLog(REDIS_NOTICE,"DB loaded from append only file: %ld seconds",time(NULL)-start); + redisLog(REDIS_NOTICE,"DB loaded from append only file: %.3f seconds",(float)(ustime()-start)/1000000); } else { if (rdbLoad(server.dbfilename) == REDIS_OK) - redisLog(REDIS_NOTICE,"DB loaded from disk: %ld seconds",time(NULL)-start); + redisLog(REDIS_NOTICE,"DB loaded from disk: %.3f seconds",(float)(ustime()-start)/1000000); } if (server.ipfd > 0) redisLog(REDIS_NOTICE,"The server is now ready to accept connections on port %d", server.port); @@ -1682,10 +1705,8 @@ int main(int argc, char **argv) { return 0; } -/* ============================= Backtrace support ========================= */ - #ifdef HAVE_BACKTRACE -void *getMcontextEip(ucontext_t *uc) { +static void *getMcontextEip(ucontext_t *uc) { #if defined(__FreeBSD__) return (void*) uc->uc_mcontext.mc_eip; #elif defined(__dietlibc__) @@ -1713,7 +1734,7 @@ void *getMcontextEip(ucontext_t *uc) { #endif } -void segvHandler(int sig, siginfo_t *info, void *secret) { +static void sigsegvHandler(int sig, siginfo_t *info, void *secret) { void *trace[100]; char **messages = NULL; int i, trace_size = 0; @@ -1725,7 +1746,7 @@ void segvHandler(int sig, siginfo_t *info, void *secret) { redisLog(REDIS_WARNING, "======= Ooops! Redis %s got signal: -%d- =======", REDIS_VERSION, sig); infostring = genRedisInfoString("all"); - redisLog(REDIS_WARNING, "%s",infostring); + redisLogRaw(REDIS_WARNING, infostring); /* It's not safe to sdsfree() the returned string under memory * corruption conditions. Let it leak as we are going to abort */ @@ -1752,37 +1773,35 @@ void segvHandler(int sig, siginfo_t *info, void *secret) { sigaction (sig, &act, NULL); kill(getpid(),sig); } +#endif /* HAVE_BACKTRACE */ -void sigtermHandler(int sig) { +static void sigtermHandler(int sig) { REDIS_NOTUSED(sig); - redisLog(REDIS_WARNING,"SIGTERM received, scheduling shutting down..."); + redisLog(REDIS_WARNING,"Received SIGTERM, scheduling shutdown..."); server.shutdown_asap = 1; } -void setupSigSegvAction(void) { +void setupSignalHandlers(void) { struct sigaction act; - sigemptyset (&act.sa_mask); - /* When the SA_SIGINFO flag is set in sa_flags then sa_sigaction - * is used. Otherwise, sa_handler is used */ - act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO; - act.sa_sigaction = segvHandler; - sigaction (SIGSEGV, &act, NULL); - sigaction (SIGBUS, &act, NULL); - sigaction (SIGFPE, &act, NULL); - sigaction (SIGILL, &act, NULL); - sigaction (SIGBUS, &act, 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_handler = sigtermHandler; - sigaction (SIGTERM, &act, NULL); - return; -} + sigaction(SIGTERM, &act, NULL); -#else /* HAVE_BACKTRACE */ -void setupSigSegvAction(void) { +#ifdef HAVE_BACKTRACE + sigemptyset(&act.sa_mask); + act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO; + act.sa_sigaction = sigsegvHandler; + sigaction(SIGSEGV, &act, NULL); + sigaction(SIGBUS, &act, NULL); + sigaction(SIGFPE, &act, NULL); + sigaction(SIGILL, &act, NULL); +#endif + return; } -#endif /* HAVE_BACKTRACE */ /* The End */