+ int trace_size = 0, fd;
+
+ /* Open the log file in append mode. */
+ fd = server.logfile ?
+ open(server.logfile, O_APPEND|O_CREAT|O_WRONLY, 0644) :
+ STDOUT_FILENO;
+ if (fd == -1) return;
+
+ /* Generate the stack trace */
+ trace_size = backtrace(trace, 100);
+
+ /* overwrite sigaction with caller's address */
+ if (getMcontextEip(uc) != NULL)
+ trace[1] = getMcontextEip(uc);
+
+ /* Write symbols to log file */
+ backtrace_symbols_fd(trace, trace_size, fd);
+
+ /* Cleanup */
+ if (server.logfile) close(fd);
+}
+
+/* Log information about the "current" client, that is, the client that is
+ * currently being served by Redis. May be NULL if Redis is not serving a
+ * client right now. */
+void logCurrentClient(void) {
+ if (server.current_client == NULL) return;
+
+ redisClient *cc = server.current_client;
+ sds client;
+ int j;
+
+ redisLog(REDIS_WARNING, "--- CURRENT CLIENT INFO");
+ client = getClientInfoString(cc);
+ redisLog(REDIS_WARNING,"client: %s", client);
+ sdsfree(client);
+ 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);
+ }
+}
+
+#if defined(HAVE_PROC_MAPS)
+int memtest_non_destructive(void *addr, size_t size); /* memtest.c */
+
+int memtest_test_linux_anonymous_maps(void) {
+ FILE *fp = fopen("/proc/self/maps","r");
+ char line[1024];
+ size_t start_addr, end_addr, size;
+
+ while(fgets(line,sizeof(line),fp) != NULL) {
+ char *start, *end, *p = line;
+ int j;
+
+ start = p;
+ p = strchr(p,'-');
+ if (!p) continue;
+ *p++ = '\0';
+ end = p;
+ p = strchr(p,' ');
+ if (!p) continue;
+ *p++ = '\0';
+ if (strstr(p,"stack") ||
+ strstr(p,"vdso") ||
+ strstr(p,"vsyscall")) continue;
+ if (!strstr(p,"00:00")) continue;
+ if (!strstr(p,"rw")) continue;
+
+ start_addr = strtoul(start,NULL,16);
+ end_addr = strtoul(end,NULL,16);
+ size = end_addr-start_addr;
+ redisLog(REDIS_WARNING,
+ "Testing memory at %lx (%lu bytes)", start_addr, size);
+ for (j = 0; j < 3; j++) {
+ if (memtest_non_destructive((void*)start_addr,size) != 0) {
+ fclose(fp);
+ return 1;
+ }
+ }
+ }
+ fclose(fp);
+ return 0;
+}
+#endif
+
+void sigsegvHandler(int sig, siginfo_t *info, void *secret) {