summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cluster.c2
-rw-r--r--src/debug.c4
-rw-r--r--src/redis.c22
-rw-r--r--src/zmalloc.c14
-rw-r--r--src/zmalloc.h1
5 files changed, 25 insertions, 18 deletions
diff --git a/src/cluster.c b/src/cluster.c
index e87ca45a9..57243132d 100644
--- a/src/cluster.c
+++ b/src/cluster.c
@@ -210,7 +210,7 @@ void clusterInit(void) {
exit(1);
}
if (aeCreateFileEvent(server.el, server.cfd, AE_READABLE,
- clusterAcceptHandler, NULL) == AE_ERR) oom("creating file event");
+ clusterAcceptHandler, NULL) == AE_ERR) redisPanic("Unrecoverable error creating Redis Cluster file event.");
server.cluster.slots_to_keys = zslCreate();
}
diff --git a/src/debug.c b/src/debug.c
index e56862882..566b2b959 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -218,6 +218,10 @@ void computeDatasetDigest(unsigned char *final) {
void debugCommand(redisClient *c) {
if (!strcasecmp(c->argv[1]->ptr,"segfault")) {
*((char*)-1) = 'x';
+ } else if (!strcasecmp(c->argv[1]->ptr,"oom")) {
+ void *ptr = zmalloc(ULONG_MAX); /* Should trigger an out of memory. */
+ zfree(ptr);
+ addReply(c,shared.ok);
} else if (!strcasecmp(c->argv[1]->ptr,"assert")) {
if (c->argc >= 3) c->argv[2] = tryObjectEncoding(c->argv[2]);
redisAssertWithInfo(c,c->argv[0],1 == 2);
diff --git a/src/redis.c b/src/redis.c
index f2c5e2c70..92f1323b3 100644
--- a/src/redis.c
+++ b/src/redis.c
@@ -334,17 +334,6 @@ err:
if (server.logfile) close(fd);
}
-/* Redis generally does not try to recover from out of memory conditions
- * when allocating objects or strings, it is not clear if it will be possible
- * to report this condition to the client since the networking layer itself
- * is based on heap allocation for send buffers, so we simply abort.
- * At least the code will be simpler to read... */
-void oom(const char *msg) {
- redisLog(REDIS_WARNING, "%s: Out of memory\n",msg);
- sleep(1);
- abort();
-}
-
/* Return the UNIX time in microseconds */
long long ustime(void) {
struct timeval tv;
@@ -1337,9 +1326,9 @@ void initServer() {
server.stop_writes_on_bgsave_err = 1;
aeCreateTimeEvent(server.el, 1, serverCron, NULL, NULL);
if (server.ipfd > 0 && aeCreateFileEvent(server.el,server.ipfd,AE_READABLE,
- acceptTcpHandler,NULL) == AE_ERR) oom("creating file event");
+ acceptTcpHandler,NULL) == AE_ERR) redisPanic("Unrecoverable error creating server.ipfd file event.");
if (server.sofd > 0 && aeCreateFileEvent(server.el,server.sofd,AE_READABLE,
- acceptUnixHandler,NULL) == AE_ERR) oom("creating file event");
+ acceptUnixHandler,NULL) == AE_ERR) redisPanic("Unrecoverable error creating server.sofd file event.");
if (server.aof_state == REDIS_AOF_ON) {
server.aof_fd = open(server.aof_filename,
@@ -2535,11 +2524,18 @@ void loadDataFromDisk(void) {
}
}
+void redisOutOfMemoryHandler(size_t allocation_size) {
+ redisLog(REDIS_WARNING,"Out Of Memory allocating %zu bytes!",
+ allocation_size);
+ redisPanic("OOM");
+}
+
int main(int argc, char **argv) {
struct timeval tv;
/* We need to initialize our libraries, and the server configuration. */
zmalloc_enable_thread_safeness();
+ zmalloc_set_oom_handler(redisOutOfMemoryHandler);
srand(time(NULL)^getpid());
gettimeofday(&tv,NULL);
dictSetHashFunctionSeed(tv.tv_sec^tv.tv_usec^getpid());
diff --git a/src/zmalloc.c b/src/zmalloc.c
index 79b561586..afa9fda80 100644
--- a/src/zmalloc.c
+++ b/src/zmalloc.c
@@ -109,17 +109,19 @@ static size_t used_memory = 0;
static int zmalloc_thread_safe = 0;
pthread_mutex_t used_memory_mutex = PTHREAD_MUTEX_INITIALIZER;
-static void zmalloc_oom(size_t size) {
+static void zmalloc_default_oom(size_t size) {
fprintf(stderr, "zmalloc: Out of memory trying to allocate %zu bytes\n",
size);
fflush(stderr);
abort();
}
+static void (*zmalloc_oom_handler)(size_t) = zmalloc_default_oom;
+
void *zmalloc(size_t size) {
void *ptr = malloc(size+PREFIX_SIZE);
- if (!ptr) zmalloc_oom(size);
+ if (!ptr) zmalloc_oom_handler(size);
#ifdef HAVE_MALLOC_SIZE
update_zmalloc_stat_alloc(zmalloc_size(ptr),size);
return ptr;
@@ -133,7 +135,7 @@ void *zmalloc(size_t size) {
void *zcalloc(size_t size) {
void *ptr = calloc(1, size+PREFIX_SIZE);
- if (!ptr) zmalloc_oom(size);
+ if (!ptr) zmalloc_oom_handler(size);
#ifdef HAVE_MALLOC_SIZE
update_zmalloc_stat_alloc(zmalloc_size(ptr),size);
return ptr;
@@ -155,7 +157,7 @@ void *zrealloc(void *ptr, size_t size) {
#ifdef HAVE_MALLOC_SIZE
oldsize = zmalloc_size(ptr);
newptr = realloc(ptr,size);
- if (!newptr) zmalloc_oom(size);
+ if (!newptr) zmalloc_oom_handler(size);
update_zmalloc_stat_free(oldsize);
update_zmalloc_stat_alloc(zmalloc_size(newptr),size);
@@ -236,6 +238,10 @@ void zmalloc_enable_thread_safeness(void) {
zmalloc_thread_safe = 1;
}
+void zmalloc_set_oom_handler(void (*oom_handler)(size_t)) {
+ zmalloc_oom_handler = oom_handler;
+}
+
/* Get the RSS information in an OS-specific way.
*
* WARNING: the function zmalloc_get_rss() is not designed to be fast
diff --git a/src/zmalloc.h b/src/zmalloc.h
index 89f5b6ee0..14e79534e 100644
--- a/src/zmalloc.h
+++ b/src/zmalloc.h
@@ -72,6 +72,7 @@ void zfree(void *ptr);
char *zstrdup(const char *s);
size_t zmalloc_used_memory(void);
void zmalloc_enable_thread_safeness(void);
+void zmalloc_set_oom_handler(void (*oom_handler)(size_t));
float zmalloc_get_fragmentation_ratio(void);
size_t zmalloc_get_rss(void);
void zlibc_free(void *ptr);