]> git.saurik.com Git - redis.git/commitdiff
On crash print information about the current client (if any), command vector, and...
authorantirez <antirez@gmail.com>
Thu, 12 Jan 2012 15:02:57 +0000 (16:02 +0100)
committerantirez <antirez@gmail.com>
Thu, 12 Jan 2012 15:02:57 +0000 (16:02 +0100)
src/debug.c
src/networking.c
src/redis.c
src/redis.h

index d218f0f93179fc74e4ff4fc53c12cbf04bee4a2d..728aa8a18cc052277f8520759d4cb916e845267e 100644 (file)
@@ -336,9 +336,7 @@ void _redisAssertPrintClientInfo(redisClient *c) {
     }
 }
 
     }
 }
 
-void _redisAssertPrintObject(robj *o) {
-    bugReportStart();
-    redisLog(REDIS_WARNING,"=== ASSERTION FAILED OBJECT CONTEXT ===");
+void redisLogObjectDebugInfo(robj *o) {
     redisLog(REDIS_WARNING,"Object type: %d", o->type);
     redisLog(REDIS_WARNING,"Object encoding: %d", o->encoding);
     redisLog(REDIS_WARNING,"Object refcount: %d", o->refcount);
     redisLog(REDIS_WARNING,"Object type: %d", o->type);
     redisLog(REDIS_WARNING,"Object encoding: %d", o->encoding);
     redisLog(REDIS_WARNING,"Object refcount: %d", o->refcount);
@@ -346,9 +344,25 @@ void _redisAssertPrintObject(robj *o) {
         redisLog(REDIS_WARNING,"Object raw string len: %d", sdslen(o->ptr));
         if (sdslen(o->ptr) < 4096)
             redisLog(REDIS_WARNING,"Object raw string content: \"%s\"", (char*)o->ptr);
         redisLog(REDIS_WARNING,"Object raw string len: %d", sdslen(o->ptr));
         if (sdslen(o->ptr) < 4096)
             redisLog(REDIS_WARNING,"Object raw string content: \"%s\"", (char*)o->ptr);
+    } else if (o->type == REDIS_LIST) {
+        redisLog(REDIS_WARNING,"List length: %d", (int) listTypeLength(o));
+    } else if (o->type == REDIS_SET) {
+        redisLog(REDIS_WARNING,"Set size: %d", (int) setTypeSize(o));
+    } else if (o->type == REDIS_HASH) {
+        redisLog(REDIS_WARNING,"Hash size: %d", (int) hashTypeLength(o));
+    } else if (o->type == REDIS_ZSET) {
+        redisLog(REDIS_WARNING,"Sorted set size: %d", (int) zsetLength(o));
+        if (o->encoding == REDIS_ENCODING_SKIPLIST)
+            redisLog(REDIS_WARNING,"Skiplist level: %d", (int) ((zset*)o->ptr)->zsl->level);
     }
 }
 
     }
 }
 
+void _redisAssertPrintObject(robj *o) {
+    bugReportStart();
+    redisLog(REDIS_WARNING,"=== ASSERTION FAILED OBJECT CONTEXT ===");
+    redisLogObjectDebugInfo(o);
+}
+
 void _redisAssertWithInfo(redisClient *c, robj *o, char *estr, char *file, int line) {
     if (c) _redisAssertPrintClientInfo(c);
     if (o) _redisAssertPrintObject(o);
 void _redisAssertWithInfo(redisClient *c, robj *o, char *estr, char *file, int line) {
     if (c) _redisAssertPrintClientInfo(c);
     if (o) _redisAssertPrintObject(o);
index ddb171b32d470658558fdc0209e3d6c645000170..8a025db35f53225b7b65312b689c491ca8c16f93 100644 (file)
@@ -481,6 +481,9 @@ static void freeClientArgv(redisClient *c) {
 void freeClient(redisClient *c) {
     listNode *ln;
 
 void freeClient(redisClient *c) {
     listNode *ln;
 
+    /* If this is marked as current client unset it */
+    if (server.current_client == c) server.current_client = NULL;
+
     /* Note that if the client we are freeing is blocked into a blocking
      * call, we have to set querybuf to NULL *before* to call
      * unblockClientWaitingData() to avoid processInputBuffer() will get
     /* Note that if the client we are freeing is blocked into a blocking
      * call, we have to set querybuf to NULL *before* to call
      * unblockClientWaitingData() to avoid processInputBuffer() will get
@@ -900,6 +903,7 @@ void readQueryFromClient(aeEventLoop *el, int fd, void *privdata, int mask) {
     REDIS_NOTUSED(el);
     REDIS_NOTUSED(mask);
 
     REDIS_NOTUSED(el);
     REDIS_NOTUSED(mask);
 
+    server.current_client = c;
     readlen = REDIS_IOBUF_LEN;
     /* If this is a multi bulk request, and we are processing a bulk reply
      * that is large enough, try to maximize the probabilty that the query
     readlen = REDIS_IOBUF_LEN;
     /* If this is a multi bulk request, and we are processing a bulk reply
      * that is large enough, try to maximize the probabilty that the query
@@ -935,6 +939,7 @@ void readQueryFromClient(aeEventLoop *el, int fd, void *privdata, int mask) {
         sdsIncrLen(c->querybuf,nread);
         c->lastinteraction = time(NULL);
     } else {
         sdsIncrLen(c->querybuf,nread);
         c->lastinteraction = time(NULL);
     } else {
+        server.current_client = NULL;
         return;
     }
     if (sdslen(c->querybuf) > server.client_max_querybuf_len) {
         return;
     }
     if (sdslen(c->querybuf) > server.client_max_querybuf_len) {
@@ -948,6 +953,7 @@ void readQueryFromClient(aeEventLoop *el, int fd, void *privdata, int mask) {
         return;
     }
     processInputBuffer(c);
         return;
     }
     processInputBuffer(c);
+    server.current_client = NULL;
 }
 
 void getClientsMaxBuffers(unsigned long *longest_output_list,
 }
 
 void getClientsMaxBuffers(unsigned long *longest_output_list,
index 5b585c479828817689653d8169d029bb91a5aa0e..6e897d83c0ecf2c7dbbc4df45a69ddbf9df3b00c 100644 (file)
@@ -787,8 +787,11 @@ void beforeSleep(struct aeEventLoop *eventLoop) {
         c->flags &= ~REDIS_UNBLOCKED;
 
         /* Process remaining data in the input buffer. */
         c->flags &= ~REDIS_UNBLOCKED;
 
         /* Process remaining data in the input buffer. */
-        if (c->querybuf && sdslen(c->querybuf) > 0)
+        if (c->querybuf && sdslen(c->querybuf) > 0) {
+            server.current_client = c;
             processInputBuffer(c);
             processInputBuffer(c);
+            server.current_client = NULL;
+        }
     }
 
     /* Write the AOF buffer on disk */
     }
 
     /* Write the AOF buffer on disk */
@@ -1002,6 +1005,7 @@ void initServer() {
             server.syslog_facility);
     }
 
             server.syslog_facility);
     }
 
+    server.current_client = NULL;
     server.clients = listCreate();
     server.slaves = listCreate();
     server.monitors = listCreate();
     server.clients = listCreate();
     server.slaves = listCreate();
     server.monitors = listCreate();
@@ -2005,6 +2009,40 @@ static void sigsegvHandler(int sig, siginfo_t *info, void *secret) {
     redisLogRaw(REDIS_WARNING, clients);
     /* Don't sdsfree() strings to avoid a crash. Memory may be corrupted. */
 
     redisLogRaw(REDIS_WARNING, clients);
     /* Don't sdsfree() strings to avoid a crash. Memory may be corrupted. */
 
+    /* Log CURRENT CLIENT info */
+    if (server.current_client) {
+        redisClient *cc = server.current_client;
+        sds client;
+        int j;
+
+        redisLog(REDIS_WARNING, "--- CURRENT CLIENT INFO");
+        client = getClientInfoString(cc);
+        redisLog(REDIS_WARNING,"client: %s", client);
+        /* Missing sdsfree(client) to avoid crash if memory is corrupted. */
+        for (j = 0; j < cc->argc; j++) {
+            robj *decoded;
+
+            decoded = getDecodedObject(cc->argv[j]);
+            redisLog(REDIS_WARNING,"argv[%d]: '%s'", j, (char*)decoded->ptr);
+            decrRefCount(decoded);
+        }
+        /* Check if the first argument, usually a key, is found inside the
+         * selected DB, and if so print info about the associated object. */
+        if (cc->argc >= 1) {
+            robj *val, *key;
+            dictEntry *de;
+
+            key = getDecodedObject(cc->argv[1]);
+            de = dictFind(cc->db->dict, key->ptr);
+            if (de) {
+                val = dictGetVal(de);
+                redisLog(REDIS_WARNING,"key '%s' found in DB containing the following object:", key->ptr);
+                redisLogObjectDebugInfo(val);
+            }
+            decrRefCount(key);
+        }
+    }
+
     redisLog(REDIS_WARNING,
 "=== REDIS BUG REPORT END. Make sure to include from START to END. ===\n\n"
 "    Please report the crash opening an issue on github:\n\n"
     redisLog(REDIS_WARNING,
 "=== REDIS BUG REPORT END. Make sure to include from START to END. ===\n\n"
 "    Please report the crash opening an issue on github:\n\n"
index f3b3134e0042fb1528b29fd83700d09d5bb690b3..1ac2a2d287b7d74222a62520074e4a1d66c29327 100644 (file)
@@ -519,6 +519,7 @@ struct redisServer {
     int cfd;                    /* Cluster bus lisetning socket */
     list *clients;              /* List of active clients */
     list *slaves, *monitors;    /* List of slaves and MONITORs */
     int cfd;                    /* Cluster bus lisetning socket */
     list *clients;              /* List of active clients */
     list *slaves, *monitors;    /* List of slaves and MONITORs */
+    redisClient *current_client; /* Current client, only used on crash report */
     char neterr[ANET_ERR_LEN];  /* Error buffer for anet.c */
     /* RDB / AOF loading information */
     int loading;                /* We are loading data from disk if true */
     char neterr[ANET_ERR_LEN];  /* Error buffer for anet.c */
     /* RDB / AOF loading information */
     int loading;                /* We are loading data from disk if true */
@@ -1159,5 +1160,6 @@ void _redisAssertWithInfo(redisClient *c, robj *o, char *estr, char *file, int l
 void _redisAssert(char *estr, char *file, int line);
 void _redisPanic(char *msg, char *file, int line);
 void bugReportStart(void);
 void _redisAssert(char *estr, char *file, int line);
 void _redisPanic(char *msg, char *file, int line);
 void bugReportStart(void);
+void redisLogObjectDebugInfo(robj *o);
 
 #endif
 
 #endif