提交 00010fa9 编写于 作者: A antirez

On crash print information about the current client (if any), command vector,...

On crash print information about the current client (if any), command vector, and object associated to first argument assuming it is a key.
上级 d8bd12f9
......@@ -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);
......@@ -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);
} 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);
......
......@@ -481,6 +481,9 @@ static void freeClientArgv(redisClient *c) {
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
......@@ -900,6 +903,7 @@ void readQueryFromClient(aeEventLoop *el, int fd, void *privdata, int 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
......@@ -935,6 +939,7 @@ void readQueryFromClient(aeEventLoop *el, int fd, void *privdata, int mask) {
sdsIncrLen(c->querybuf,nread);
c->lastinteraction = time(NULL);
} else {
server.current_client = NULL;
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);
server.current_client = NULL;
}
void getClientsMaxBuffers(unsigned long *longest_output_list,
......
......@@ -787,8 +787,11 @@ void beforeSleep(struct aeEventLoop *eventLoop) {
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);
server.current_client = NULL;
}
}
/* Write the AOF buffer on disk */
......@@ -1002,6 +1005,7 @@ void initServer() {
server.syslog_facility);
}
server.current_client = NULL;
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. */
/* 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"
......
......@@ -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 */
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 */
......@@ -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 redisLogObjectDebugInfo(robj *o);
#endif
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册