]> git.saurik.com Git - redis.git/commitdiff
Merge git://github.com/dierbro/redis
authorantirez <antirez@gmail.com>
Sat, 6 Jun 2009 21:40:48 +0000 (23:40 +0200)
committerantirez <antirez@gmail.com>
Sat, 6 Jun 2009 21:40:48 +0000 (23:40 +0200)
Makefile
redis.c
redis.h [new file with mode: 0644]

index f7c546470bca60c39e5e658a072801f63140ee6a..fda703e1e2d74ae40c438ab13897761961d22572 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,8 +2,8 @@
 # Copyright (C) 2009 Salvatore Sanfilippo <antirez at gmail dot com>
 # This file is released under the BSD license, see the COPYING file
 
-DEBUG?= -g
-CFLAGS?= -std=c99 -pedantic -O2 -Wall -W -DSDS_ABORT_ON_OOM
+DEBUG?= -g -rdynamic -ggdb 
+CFLAGS?= -std=c99 -pedantic -O0 -Wall -W -DSDS_ABORT_ON_OOM
 CCOPT= $(CFLAGS)
 
 OBJ = adlist.o ae.o anet.o dict.o redis.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o
diff --git a/redis.c b/redis.c
index f9fb368231cff6c732e0292d71334cf97087fc2a..56ddee9e130a5d3eae3dff8d2cd778f77f98d963 100644 (file)
--- a/redis.c
+++ b/redis.c
 #include <string.h>
 #include <time.h>
 #include <unistd.h>
+#define __USE_POSIX199309
 #include <signal.h>
+#include <execinfo.h>
+#include <ucontext.h>
 #include <sys/wait.h>
 #include <errno.h>
 #include <assert.h>
@@ -51,6 +54,7 @@
 #include <limits.h>
 #include <execinfo.h>
 
+#include "redis.h"
 #include "ae.h"     /* Event driven programming library */
 #include "sds.h"    /* Dynamic safe strings */
 #include "anet.h"   /* Networking the easy way */
 /* Anti-warning macro... */
 #define REDIS_NOTUSED(V) ((void) V)
 
+
 /*================================= Data types ============================== */
 
 /* A redis object, that is a type able to hold a string / list / set */
@@ -272,6 +277,11 @@ struct redisCommand {
     int flags;
 };
 
+struct redisFunctionSym {
+    char *name;
+    long pointer;
+};
+
 typedef struct _redisSortObject {
     robj *obj;
     union {
@@ -319,6 +329,7 @@ static time_t getExpire(redisDb *db, robj *key);
 static int setExpire(redisDb *db, robj *key, time_t when);
 static void updateSalvesWaitingBgsave(int bgsaveerr);
 static void freeMemoryIfNeeded(void);
+static int processCommand(redisClient *c);
 
 static void authCommand(redisClient *c);
 static void pingCommand(redisClient *c);
@@ -377,7 +388,7 @@ static void getSetCommand(redisClient *c);
 static void ttlCommand(redisClient *c);
 static void slaveofCommand(redisClient *c);
 static void debugCommand(redisClient *c);
-
+static void setupSigSegvAction();
 /*================================= Globals ================================= */
 
 /* Global vars */
@@ -443,7 +454,91 @@ static struct redisCommand cmdTable[] = {
     {"debug",debugCommand,-2,REDIS_CMD_INLINE},
     {NULL,NULL,0,0}
 };
-
+static struct redisFunctionSym symsTable[] = {
+{"freeStringObject", (long)freeStringObject},
+{"freeListObject", (long)freeListObject},
+{"freeSetObject", (long)freeSetObject},
+{"decrRefCount", (long)decrRefCount},
+{"createObject", (long)createObject},
+{"freeClient", (long)freeClient},
+{"rdbLoad", (long)rdbLoad},
+{"addReply", (long)addReply},
+{"addReplySds", (long)addReplySds},
+{"incrRefCount", (long)incrRefCount},
+{"rdbSaveBackground", (long)rdbSaveBackground},
+{"createStringObject", (long)createStringObject},
+{"replicationFeedSlaves", (long)replicationFeedSlaves},
+{"syncWithMaster", (long)syncWithMaster},
+{"tryObjectSharing", (long)tryObjectSharing},
+{"removeExpire", (long)removeExpire},
+{"expireIfNeeded", (long)expireIfNeeded},
+{"deleteIfVolatile", (long)deleteIfVolatile},
+{"deleteKey", (long)deleteKey},
+{"getExpire", (long)getExpire},
+{"setExpire", (long)setExpire},
+{"updateSalvesWaitingBgsave", (long)updateSalvesWaitingBgsave},
+{"freeMemoryIfNeeded", (long)freeMemoryIfNeeded},
+{"authCommand", (long)authCommand},
+{"pingCommand", (long)pingCommand},
+{"echoCommand", (long)echoCommand},
+{"setCommand", (long)setCommand},
+{"setnxCommand", (long)setnxCommand},
+{"getCommand", (long)getCommand},
+{"delCommand", (long)delCommand},
+{"existsCommand", (long)existsCommand},
+{"incrCommand", (long)incrCommand},
+{"decrCommand", (long)decrCommand},
+{"incrbyCommand", (long)incrbyCommand},
+{"decrbyCommand", (long)decrbyCommand},
+{"selectCommand", (long)selectCommand},
+{"randomkeyCommand", (long)randomkeyCommand},
+{"keysCommand", (long)keysCommand},
+{"dbsizeCommand", (long)dbsizeCommand},
+{"lastsaveCommand", (long)lastsaveCommand},
+{"saveCommand", (long)saveCommand},
+{"bgsaveCommand", (long)bgsaveCommand},
+{"shutdownCommand", (long)shutdownCommand},
+{"moveCommand", (long)moveCommand},
+{"renameCommand", (long)renameCommand},
+{"renamenxCommand", (long)renamenxCommand},
+{"lpushCommand", (long)lpushCommand},
+{"rpushCommand", (long)rpushCommand},
+{"lpopCommand", (long)lpopCommand},
+{"rpopCommand", (long)rpopCommand},
+{"llenCommand", (long)llenCommand},
+{"lindexCommand", (long)lindexCommand},
+{"lrangeCommand", (long)lrangeCommand},
+{"ltrimCommand", (long)ltrimCommand},
+{"typeCommand", (long)typeCommand},
+{"lsetCommand", (long)lsetCommand},
+{"saddCommand", (long)saddCommand},
+{"sremCommand", (long)sremCommand},
+{"smoveCommand", (long)smoveCommand},
+{"sismemberCommand", (long)sismemberCommand},
+{"scardCommand", (long)scardCommand},
+{"sinterCommand", (long)sinterCommand},
+{"sinterstoreCommand", (long)sinterstoreCommand},
+{"sunionCommand", (long)sunionCommand},
+{"sunionstoreCommand", (long)sunionstoreCommand},
+{"sdiffCommand", (long)sdiffCommand},
+{"sdiffstoreCommand", (long)sdiffstoreCommand},
+{"syncCommand", (long)syncCommand},
+{"flushdbCommand", (long)flushdbCommand},
+{"flushallCommand", (long)flushallCommand},
+{"sortCommand", (long)sortCommand},
+{"lremCommand", (long)lremCommand},
+{"infoCommand", (long)infoCommand},
+{"mgetCommand", (long)mgetCommand},
+{"monitorCommand", (long)monitorCommand},
+{"expireCommand", (long)expireCommand},
+{"getSetCommand", (long)getSetCommand},
+{"ttlCommand", (long)ttlCommand},
+{"slaveofCommand", (long)slaveofCommand},
+{"debugCommand", (long)debugCommand},
+{"processCommand", (long)processCommand},
+{"setupSigSegvAction", (long)setupSigSegvAction},
+{NULL,0}
+};
 /*============================ Utility functions ============================ */
 
 /* Glob-style pattern matching. */
@@ -902,6 +997,7 @@ static void initServer() {
 
     signal(SIGHUP, SIG_IGN);
     signal(SIGPIPE, SIG_IGN);
+    setupSigSegvAction();
 
     server.clients = listCreate();
     server.slaves = listCreate();
@@ -4096,7 +4192,94 @@ static void debugCommand(redisClient *c) {
             "-ERR Syntax error, try DEBUG [SEGFAULT|OBJECT <key>]\r\n"));
     }
 }
-
+char *findFuncName(void *pointer, long *offset){
+       int i, ret=-1;
+       long val, off;
+       for(i=0; symsTable[i].pointer!=0; i++){
+               val=(long)pointer-symsTable[i].pointer;
+               if(val>=0 && (off<0 || val <= off)){
+                       off=val;
+                       ret=i;
+               }
+       }
+       if(ret<0)
+               *offset=0;
+       else
+               *offset=off;
+       return ret>=0?symsTable[ret].name:"unknown";
+}
+
+static void segvHandler (int sig, siginfo_t *info, void *secret) {
+
+  void *trace[100];
+  char **messages = (char **)NULL;
+  char *tmp;
+  int i, trace_size = 0;
+  long offset=0;
+  ucontext_t *uc = (ucontext_t *)secret;
+  time_t uptime = time(NULL)-server.stat_starttime;
+
+  redisLog(REDIS_WARNING, "application: redis,  signal: segmentation fault -%d-",REDIS_VERSION, sig);
+  redisLog(REDIS_WARNING, "%s", sdscatprintf(sdsempty(),
+        "redis_version:%s; "
+        "uptime_in_days:%d; "
+        "connected_clients:%d; "
+        "connected_slaves:%d; "
+        "used_memory:%zu; "
+        "changes_since_last_save:%lld; "
+        "bgsave_in_progress:%d; "
+        "last_save_time:%d; "
+        "total_connections_received:%lld; "
+        "total_commands_processed:%lld; "
+        "role:%s;"
+        ,REDIS_VERSION,
+        uptime,
+        listLength(server.clients)-listLength(server.slaves),
+        listLength(server.slaves),
+        server.usedmemory,
+        server.dirty,
+        server.bgsaveinprogress,
+        server.lastsave,
+        server.stat_numconnections,
+        server.stat_numcommands,
+        server.masterhost == NULL ? "master" : "slave"
+    ));
+
+  redisLog(REDIS_WARNING,"EIP %p",  (void *)uc->uc_mcontext.gregs[REG_EIP]);
+  redisLog(REDIS_WARNING,"EAX %p, EBX %p,  ECX %p, EDX %p", (void *)uc->uc_mcontext.gregs[REG_EAX], (void *)uc->uc_mcontext.gregs[REG_EBX],  (void *)uc->uc_mcontext.gregs[REG_ECX], (void *)uc->uc_mcontext.gregs[REG_EDX]);
+       
+  trace_size = backtrace(trace, 100);
+  char pointer[trace_size][11];
+    /* overwrite sigaction with caller's address */
+  trace[1] = (void *) uc->uc_mcontext.gregs[REG_EIP];
+ for (i=1; i<trace_size; ++i)
+       snprintf(pointer[i],11,"[%p]", trace[i]);
+
+  messages = backtrace_symbols(trace, trace_size);
+  
+  for (i=1; i<trace_size; ++i){
+       tmp=strstr(messages[i],pointer[i]);
+       if((tmp-2)[0]!=')'){
+               char *a=findFuncName(trace[i], &offset);
+               redisLog(REDIS_WARNING,"#%d (%s+0x%x) %s", i, a, (unsigned int)offset, tmp);
+               }
+       else
+               redisLog(REDIS_WARNING,"#%d %s", i, messages[i]);
+       }
+
+  free(messages);
+  exit(0);
+}
+
+void setupSigSegvAction(){
+  struct sigaction act;
+  sigemptyset (&act.sa_mask);
+  /* When the SA_SIGINFO flag is set in sa_flags then sa_sigaction  is used. Otherwise, sa_handler is used */
+  act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO;
+  act.sa_sigaction = segvHandler;
+  sigaction (SIGSEGV, &act, NULL);
+}
 /* =================================== Main! ================================ */
 
 #ifdef __linux__
@@ -4149,7 +4332,7 @@ int main(int argc, char **argv) {
 #ifdef __linux__
     linuxOvercommitMemoryWarning();
 #endif
-
+    
     initServerConfig();
     if (argc == 2) {
         ResetServerSaveParams();
diff --git a/redis.h b/redis.h
new file mode 100644 (file)
index 0000000..f2524c1
--- /dev/null
+++ b/redis.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2006-2009, Salvatore Sanfilippo <antirez at gmail dot com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *   * Neither the name of Redis nor the names of its contributors may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __REDIS_H__
+#define __REDIS_H__
+
+enum
+{
+  REG_GS = 0,
+# define REG_GS                REG_GS
+  REG_FS,
+# define REG_FS                REG_FS
+  REG_ES,
+# define REG_ES                REG_ES
+  REG_DS,
+# define REG_DS                REG_DS
+  REG_EDI,
+# define REG_EDI       REG_EDI
+  REG_ESI,
+# define REG_ESI       REG_ESI
+  REG_EBP,
+# define REG_EBP       REG_EBP
+  REG_ESP,
+# define REG_ESP       REG_ESP
+  REG_EBX,
+# define REG_EBX       REG_EBX
+  REG_EDX,
+# define REG_EDX       REG_EDX
+  REG_ECX,
+# define REG_ECX       REG_ECX
+  REG_EAX,
+# define REG_EAX       REG_EAX
+  REG_TRAPNO,
+# define REG_TRAPNO    REG_TRAPNO
+  REG_ERR,
+# define REG_ERR       REG_ERR
+  REG_EIP,
+# define REG_EIP       REG_EIP
+  REG_CS,
+# define REG_CS                REG_CS
+  REG_EFL,
+# define REG_EFL       REG_EFL
+  REG_UESP,
+# define REG_UESP      REG_UESP
+  REG_SS
+# define REG_SS        REG_SS
+};
+
+#endif