]> git.saurik.com Git - redis.git/commitdiff
Log from signal handlers is now safer.
authorantirez <antirez@gmail.com>
Wed, 28 Mar 2012 11:45:39 +0000 (13:45 +0200)
committerantirez <antirez@gmail.com>
Wed, 28 Mar 2012 11:45:39 +0000 (13:45 +0200)
src/debug.c
src/redis.c
src/redis.h

index 49c76824d2223c66a6a7804006bf702d43a46ab8..e7b3ba407fd756adadba96b932caf56f2aad9853 100644 (file)
@@ -682,25 +682,16 @@ void watchdogSignalHandler(int sig, siginfo_t *info, void *secret) {
     REDIS_NOTUSED(info);
     REDIS_NOTUSED(sig);
     sds st, log;
-    time_t now = time(NULL);
-    char date[128];
-    FILE *fp;
 
-    fp = (server.logfile == NULL) ? stdout : fopen(server.logfile,"a");
-    if (fp == NULL) return;
-
-    strftime(date,sizeof(date),"%d %b %H:%M:%S",localtime(&now));
-    log = sdscatprintf(sdsempty(),
-        "\n--- WATCHDOG TIMER EXPIRED (%s) ---\n",date); 
+    log = sdsnew("\n--- WATCHDOG TIMER EXPIRED ---\n");
 #ifdef HAVE_BACKTRACE
     st = getStackTrace(uc);
 #else
     st = sdsnew("Sorry: no support for backtrace().\n");
 #endif
     log = sdscatsds(log,st);
-    log = sdscat(log,"------\n\n");
-    fprintf(fp,"%s",log);
-    if (server.logfile) fclose(fp);
+    log = sdscat(log,"------\n");
+    redisLogFromHandler(REDIS_WARNING,log);
     sdsfree(st);
     sdsfree(log);
 }
index 5ee44a31932165257153f24974e6c0bdde086eea..5af2b1dfb275fcecaf62bbf99dcdca457d7de75b 100644 (file)
@@ -293,6 +293,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) :
+        STDIN_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);
+    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
@@ -2282,7 +2310,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;
 }
 
index c5812f0af03a8d5abe3ff505f51a120df42926b3..41e245575cec87efc83691f627244db13dc29025 100644 (file)
@@ -1004,6 +1004,7 @@ void alsoPropagate(struct redisCommand *cmd, int dbid, robj **argv, int argc, in
 int prepareForShutdown();
 void redisLog(int level, const char *fmt, ...);
 void redisLogRaw(int level, const char *msg);
+void redisLogFromHandler(int level, const char *msg);
 void usage();
 void updateDictResizePolicy(void);
 int htNeedsResize(dict *dict);