mirror of
https://github.com/fluencelabs/redis
synced 2025-03-19 17:10:50 +00:00
Merge git://github.com/dierbro/redis
This commit is contained in:
commit
c4cd5f393c
4
Makefile
4
Makefile
@ -2,8 +2,8 @@
|
|||||||
# Copyright (C) 2009 Salvatore Sanfilippo <antirez at gmail dot com>
|
# Copyright (C) 2009 Salvatore Sanfilippo <antirez at gmail dot com>
|
||||||
# This file is released under the BSD license, see the COPYING file
|
# This file is released under the BSD license, see the COPYING file
|
||||||
|
|
||||||
DEBUG?= -g
|
DEBUG?= -g -rdynamic -ggdb
|
||||||
CFLAGS?= -std=c99 -pedantic -O2 -Wall -W -DSDS_ABORT_ON_OOM
|
CFLAGS?= -std=c99 -pedantic -O0 -Wall -W -DSDS_ABORT_ON_OOM
|
||||||
CCOPT= $(CFLAGS)
|
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
|
OBJ = adlist.o ae.o anet.o dict.o redis.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o
|
||||||
|
187
redis.c
187
redis.c
@ -36,7 +36,10 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#define __USE_POSIX199309
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <execinfo.h>
|
||||||
|
#include <ucontext.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@ -51,6 +54,7 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <execinfo.h>
|
#include <execinfo.h>
|
||||||
|
|
||||||
|
#include "redis.h"
|
||||||
#include "ae.h" /* Event driven programming library */
|
#include "ae.h" /* Event driven programming library */
|
||||||
#include "sds.h" /* Dynamic safe strings */
|
#include "sds.h" /* Dynamic safe strings */
|
||||||
#include "anet.h" /* Networking the easy way */
|
#include "anet.h" /* Networking the easy way */
|
||||||
@ -171,6 +175,7 @@
|
|||||||
/* Anti-warning macro... */
|
/* Anti-warning macro... */
|
||||||
#define REDIS_NOTUSED(V) ((void) V)
|
#define REDIS_NOTUSED(V) ((void) V)
|
||||||
|
|
||||||
|
|
||||||
/*================================= Data types ============================== */
|
/*================================= Data types ============================== */
|
||||||
|
|
||||||
/* A redis object, that is a type able to hold a string / list / set */
|
/* A redis object, that is a type able to hold a string / list / set */
|
||||||
@ -272,6 +277,11 @@ struct redisCommand {
|
|||||||
int flags;
|
int flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct redisFunctionSym {
|
||||||
|
char *name;
|
||||||
|
long pointer;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct _redisSortObject {
|
typedef struct _redisSortObject {
|
||||||
robj *obj;
|
robj *obj;
|
||||||
union {
|
union {
|
||||||
@ -319,6 +329,7 @@ static time_t getExpire(redisDb *db, robj *key);
|
|||||||
static int setExpire(redisDb *db, robj *key, time_t when);
|
static int setExpire(redisDb *db, robj *key, time_t when);
|
||||||
static void updateSalvesWaitingBgsave(int bgsaveerr);
|
static void updateSalvesWaitingBgsave(int bgsaveerr);
|
||||||
static void freeMemoryIfNeeded(void);
|
static void freeMemoryIfNeeded(void);
|
||||||
|
static int processCommand(redisClient *c);
|
||||||
|
|
||||||
static void authCommand(redisClient *c);
|
static void authCommand(redisClient *c);
|
||||||
static void pingCommand(redisClient *c);
|
static void pingCommand(redisClient *c);
|
||||||
@ -377,7 +388,7 @@ static void getSetCommand(redisClient *c);
|
|||||||
static void ttlCommand(redisClient *c);
|
static void ttlCommand(redisClient *c);
|
||||||
static void slaveofCommand(redisClient *c);
|
static void slaveofCommand(redisClient *c);
|
||||||
static void debugCommand(redisClient *c);
|
static void debugCommand(redisClient *c);
|
||||||
|
static void setupSigSegvAction();
|
||||||
/*================================= Globals ================================= */
|
/*================================= Globals ================================= */
|
||||||
|
|
||||||
/* Global vars */
|
/* Global vars */
|
||||||
@ -443,7 +454,91 @@ static struct redisCommand cmdTable[] = {
|
|||||||
{"debug",debugCommand,-2,REDIS_CMD_INLINE},
|
{"debug",debugCommand,-2,REDIS_CMD_INLINE},
|
||||||
{NULL,NULL,0,0}
|
{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 ============================ */
|
/*============================ Utility functions ============================ */
|
||||||
|
|
||||||
/* Glob-style pattern matching. */
|
/* Glob-style pattern matching. */
|
||||||
@ -902,6 +997,7 @@ static void initServer() {
|
|||||||
|
|
||||||
signal(SIGHUP, SIG_IGN);
|
signal(SIGHUP, SIG_IGN);
|
||||||
signal(SIGPIPE, SIG_IGN);
|
signal(SIGPIPE, SIG_IGN);
|
||||||
|
setupSigSegvAction();
|
||||||
|
|
||||||
server.clients = listCreate();
|
server.clients = listCreate();
|
||||||
server.slaves = listCreate();
|
server.slaves = listCreate();
|
||||||
@ -4096,7 +4192,94 @@ static void debugCommand(redisClient *c) {
|
|||||||
"-ERR Syntax error, try DEBUG [SEGFAULT|OBJECT <key>]\r\n"));
|
"-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! ================================ */
|
/* =================================== Main! ================================ */
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
|
75
redis.h
Normal file
75
redis.h
Normal file
@ -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
|
Loading…
x
Reference in New Issue
Block a user