+ 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)
+void memtest_non_destructive_invert(void *addr, size_t size);
+void memtest_non_destructive_swap(void *addr, size_t size);
+#define MEMTEST_MAX_REGIONS 128
+
+int memtest_test_linux_anonymous_maps(void) {
+ FILE *fp = fopen("/proc/self/maps","r");
+ char line[1024];
+ size_t start_addr, end_addr, size;
+ size_t start_vect[MEMTEST_MAX_REGIONS];
+ size_t size_vect[MEMTEST_MAX_REGIONS];
+ int regions = 0, j;
+ uint64_t crc1 = 0, crc2 = 0, crc3 = 0;
+
+ while(fgets(line,sizeof(line),fp) != NULL) {
+ char *start, *end, *p = line;
+
+ 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;
+
+ start_vect[regions] = start_addr;
+ size_vect[regions] = size;
+ printf("Testing %lx %lu\n", start_vect[regions], size_vect[regions]);
+ regions++;
+ }
+
+ /* Test all the regions as an unique sequential region.
+ * 1) Take the CRC64 of the memory region. */
+ for (j = 0; j < regions; j++) {
+ crc1 = crc64(crc1,(void*)start_vect[j],size_vect[j]);
+ }
+
+ /* 2) Invert bits, swap adiacent words, swap again, invert bits.
+ * This is the error amplification step. */
+ for (j = 0; j < regions; j++)
+ memtest_non_destructive_invert((void*)start_vect[j],size_vect[j]);
+ for (j = 0; j < regions; j++)
+ memtest_non_destructive_swap((void*)start_vect[j],size_vect[j]);
+ for (j = 0; j < regions; j++)
+ memtest_non_destructive_swap((void*)start_vect[j],size_vect[j]);
+ for (j = 0; j < regions; j++)
+ memtest_non_destructive_invert((void*)start_vect[j],size_vect[j]);
+
+ /* 3) Take the CRC64 sum again. */
+ for (j = 0; j < regions; j++)
+ crc2 = crc64(crc2,(void*)start_vect[j],size_vect[j]);
+
+ /* 4) Swap + Swap again */
+ for (j = 0; j < regions; j++)
+ memtest_non_destructive_swap((void*)start_vect[j],size_vect[j]);
+ for (j = 0; j < regions; j++)
+ memtest_non_destructive_swap((void*)start_vect[j],size_vect[j]);
+
+ /* 5) Take the CRC64 sum again. */
+ for (j = 0; j < regions; j++)
+ crc3 = crc64(crc3,(void*)start_vect[j],size_vect[j]);
+
+ /* NOTE: It is very important to close the file descriptor only now
+ * because closing it before may result into unmapping of some memory
+ * region that we are testing. */
+ fclose(fp);
+
+ /* If the two CRC are not the same, we trapped a memory error. */
+ return crc1 != crc2 || crc2 != crc3;
+}
+#endif
+
+void sigsegvHandler(int sig, siginfo_t *info, void *secret) {