diff --git a/Makefile b/Makefile index f7c54647..fda703e1 100644 --- a/Makefile +++ b/Makefile @@ -2,8 +2,8 @@ # Copyright (C) 2009 Salvatore Sanfilippo # 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 f9fb3682..56ddee9e 100644 --- a/redis.c +++ b/redis.c @@ -36,7 +36,10 @@ #include #include #include +#define __USE_POSIX199309 #include +#include +#include #include #include #include @@ -51,6 +54,7 @@ #include #include +#include "redis.h" #include "ae.h" /* Event driven programming library */ #include "sds.h" /* Dynamic safe strings */ #include "anet.h" /* Networking the easy way */ @@ -171,6 +175,7 @@ /* 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 ]\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 + * 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