diff options
| -rw-r--r-- | deps/hiredis/.gitignore | 2 | ||||
| -rw-r--r-- | deps/hiredis/.travis.yml | 6 | ||||
| -rw-r--r-- | deps/hiredis/CHANGELOG.md | 8 | ||||
| -rw-r--r-- | deps/hiredis/Makefile | 66 | ||||
| -rw-r--r-- | deps/hiredis/README.md | 9 | ||||
| -rw-r--r-- | deps/hiredis/adapters/libuv.h | 121 | ||||
| -rw-r--r-- | deps/hiredis/async.c | 59 | ||||
| -rw-r--r-- | deps/hiredis/async.h | 1 | ||||
| -rw-r--r-- | deps/hiredis/examples/example-ae.c (renamed from deps/hiredis/example-ae.c) | 14 | ||||
| -rw-r--r-- | deps/hiredis/examples/example-libev.c (renamed from deps/hiredis/example-libev.c) | 7 | ||||
| -rw-r--r-- | deps/hiredis/examples/example-libevent.c (renamed from deps/hiredis/example-libevent.c) | 7 | ||||
| -rw-r--r-- | deps/hiredis/examples/example-libuv.c | 53 | ||||
| -rw-r--r-- | deps/hiredis/examples/example.c (renamed from deps/hiredis/example.c) | 22 | ||||
| -rw-r--r-- | deps/hiredis/fmacros.h | 4 | ||||
| -rw-r--r-- | deps/hiredis/hiredis.c | 99 | ||||
| -rw-r--r-- | deps/hiredis/hiredis.h | 20 | ||||
| -rw-r--r-- | deps/hiredis/net.c | 166 | ||||
| -rw-r--r-- | deps/hiredis/net.h | 12 | ||||
| -rw-r--r-- | deps/hiredis/sds.c | 113 | ||||
| -rw-r--r-- | deps/hiredis/sds.h | 13 | ||||
| -rw-r--r-- | deps/hiredis/test.c | 111 | ||||
| -rw-r--r-- | deps/hiredis/zmalloc.h | 13 | 
22 files changed, 730 insertions, 196 deletions
diff --git a/deps/hiredis/.gitignore b/deps/hiredis/.gitignore index 1a4d60d28..0c166a02e 100644 --- a/deps/hiredis/.gitignore +++ b/deps/hiredis/.gitignore @@ -1,5 +1,5 @@  /hiredis-test -/hiredis-example* +/examples/hiredis-example*  /*.o  /*.so  /*.dylib diff --git a/deps/hiredis/.travis.yml b/deps/hiredis/.travis.yml new file mode 100644 index 000000000..030427ff4 --- /dev/null +++ b/deps/hiredis/.travis.yml @@ -0,0 +1,6 @@ +language: c +compiler: +  - gcc +  - clang + +script: make && make check diff --git a/deps/hiredis/CHANGELOG.md b/deps/hiredis/CHANGELOG.md index d41db8a60..268b15cd5 100644 --- a/deps/hiredis/CHANGELOG.md +++ b/deps/hiredis/CHANGELOG.md @@ -1,3 +1,11 @@ +### 0.11.0 + +* Increase the maximum multi-bulk reply depth to 7. + +* Increase the read buffer size from 2k to 16k. + +* Use poll(2) instead of select(2) to support large fds (>= 1024). +  ### 0.10.1  * Makefile overhaul. Important to check out if you override one or more diff --git a/deps/hiredis/Makefile b/deps/hiredis/Makefile index 16b8767b1..ddcc4e4f6 100644 --- a/deps/hiredis/Makefile +++ b/deps/hiredis/Makefile @@ -4,11 +4,24 @@  # This file is released under the BSD license, see the COPYING file  OBJ=net.o hiredis.o sds.o async.o -BINS=hiredis-example hiredis-test +EXAMPLES=hiredis-example hiredis-example-libevent hiredis-example-libev +TESTS=hiredis-test  LIBNAME=libhiredis  HIREDIS_MAJOR=0 -HIREDIS_MINOR=10 +HIREDIS_MINOR=11 + +# redis-server configuration used for testing +REDIS_PORT=56379 +REDIS_SERVER=redis-server +define REDIS_TEST_CONFIG +	daemonize yes +	pidfile /tmp/hiredis-test-redis.pid +	port $(REDIS_PORT) +	bind 127.0.0.1 +	unixsocket /tmp/hiredis-test-redis.sock +endef +export REDIS_TEST_CONFIG  # Fallback to gcc when $CC is not in $PATH.  CC:=$(shell sh -c 'type $(CC) >/dev/null 2>/dev/null && echo $(CC) || echo gcc') @@ -41,12 +54,11 @@ ifeq ($(uname_S),Darwin)    DYLIB_MAKE_CMD=$(CC) -shared -Wl,-install_name,$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS)  endif -all: $(DYLIBNAME) $(BINS) +all: $(DYLIBNAME)  # Deps (use make dep to generate this)  net.o: net.c fmacros.h net.h hiredis.h  async.o: async.c async.h hiredis.h sds.h dict.c dict.h -example.o: example.c hiredis.h  hiredis.o: hiredis.c fmacros.h hiredis.h net.h sds.h  sds.o: sds.c sds.h  test.o: test.c hiredis.h @@ -61,36 +73,44 @@ dynamic: $(DYLIBNAME)  static: $(STLIBNAME)  # Binaries: -hiredis-example-libevent: example-libevent.c adapters/libevent.h $(STLIBNAME) -	$(CC) -o $@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -levent example-libevent.c $(STLIBNAME) +hiredis-example-libevent: examples/example-libevent.c adapters/libevent.h $(STLIBNAME) +	$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< -levent $(STLIBNAME) -hiredis-example-libev: example-libev.c adapters/libev.h $(STLIBNAME) -	$(CC) -o $@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -lev example-libev.c $(STLIBNAME) +hiredis-example-libev: examples/example-libev.c adapters/libev.h $(STLIBNAME) +	$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< -lev $(STLIBNAME)  ifndef AE_DIR  hiredis-example-ae:  	@echo "Please specify AE_DIR (e.g. <redis repository>/src)"  	@false  else -hiredis-example-ae: example-ae.c adapters/ae.h $(STLIBNAME) -	$(CC) -o $@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I$(AE_DIR) $(AE_DIR)/ae.o $(AE_DIR)/zmalloc.o example-ae.c $(STLIBNAME) +hiredis-example-ae: examples/example-ae.c adapters/ae.h $(STLIBNAME) +	$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. -I$(AE_DIR) $< $(AE_DIR)/ae.o $(AE_DIR)/zmalloc.o $(AE_DIR)/../deps/jemalloc/lib/libjemalloc.a -pthread $(STLIBNAME)  endif -hiredis-%: %.o $(STLIBNAME) +ifndef LIBUV_DIR +hiredis-example-libuv: +	@echo "Please specify LIBUV_DIR (e.g. ../libuv/)" +	@false +else +hiredis-example-libuv: examples/example-libuv.c adapters/libuv.h $(STLIBNAME) +	$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. -I$(LIBUV_DIR)/include $< $(LIBUV_DIR)/.libs/libuv.a -lpthread $(STLIBNAME) +endif + +hiredis-example: examples/example.c $(STLIBNAME) +	$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< $(STLIBNAME) + +examples: $(EXAMPLES) + +hiredis-test: test.o $(STLIBNAME)  	$(CC) -o $@ $(REAL_LDFLAGS) $< $(STLIBNAME)  test: hiredis-test  	./hiredis-test  check: hiredis-test -	echo \ -		"daemonize yes\n" \ -		"pidfile /tmp/hiredis-test-redis.pid\n" \ -		"port 56379\n" \ -		"bind 127.0.0.1\n" \ -		"unixsocket /tmp/hiredis-test-redis.sock" \ -			| redis-server - -	./hiredis-test -h 127.0.0.1 -p 56379 -s /tmp/hiredis-test-redis.sock || \ +	@echo "$$REDIS_TEST_CONFIG" | $(REDIS_SERVER) - +	./hiredis-test -h 127.0.0.1 -p $(REDIS_PORT) -s /tmp/hiredis-test-redis.sock || \  			( kill `cat /tmp/hiredis-test-redis.pid` && false )  	kill `cat /tmp/hiredis-test-redis.pid` @@ -98,17 +118,15 @@ check: hiredis-test  	$(CC) -std=c99 -pedantic -c $(REAL_CFLAGS) $<  clean: -	rm -rf $(DYLIBNAME) $(STLIBNAME) $(BINS) hiredis-example* *.o *.gcda *.gcno *.gcov +	rm -rf $(DYLIBNAME) $(STLIBNAME) $(TESTS) examples/hiredis-example* *.o *.gcda *.gcno *.gcov  dep:  	$(CC) -MM *.c  # Installation related variables and target  PREFIX?=/usr/local -INCLUDE_PATH?=include/hiredis -LIBRARY_PATH?=lib -INSTALL_INCLUDE_PATH= $(PREFIX)/$(INCLUDE_PATH) -INSTALL_LIBRARY_PATH= $(PREFIX)/$(LIBRARY_PATH) +INSTALL_INCLUDE_PATH= $(PREFIX)/include/hiredis +INSTALL_LIBRARY_PATH= $(PREFIX)/lib  ifeq ($(uname_S),SunOS)    INSTALL?= cp -r diff --git a/deps/hiredis/README.md b/deps/hiredis/README.md index 62fe1067b..dba4a8c8e 100644 --- a/deps/hiredis/README.md +++ b/deps/hiredis/README.md @@ -1,3 +1,5 @@ +[](https://travis-ci.org/redis/hiredis) +  # HIREDIS  Hiredis is a minimalistic C client library for the [Redis](http://redis.io/) database. @@ -44,7 +46,7 @@ After trying to connect to Redis using `redisConnect` you should  check the `err` field to see if establishing the connection was successful:      redisContext *c = redisConnect("127.0.0.1", 6379); -    if (c->err) { +    if (c != NULL && c->err) {          printf("Error: %s\n", c->errstr);          // handle error      } @@ -66,7 +68,7 @@ When you need to pass binary safe strings in a command, the `%b` specifier can b  used. Together with a pointer to the string, it requires a `size_t` length argument  of the string: -    reply = redisCommand(context, "SET foo %b", value, valuelen); +    reply = redisCommand(context, "SET foo %b", value, (size_t) valuelen);  Internally, Hiredis splits the command in different arguments and will  convert it to the protocol used to communicate with Redis. @@ -337,6 +339,9 @@ and a reply object (as described above) via `void **reply`. The returned status  can be either `REDIS_OK` or `REDIS_ERR`, where the latter means something went  wrong (either a protocol error, or an out of memory error). +The parser limits the level of nesting for multi bulk payloads to 7. If the +multi bulk nesting level is higher than this, the parser returns an error. +  ### Customizing replies  The function `redisReaderGetReply` creates `redisReply` and makes the function diff --git a/deps/hiredis/adapters/libuv.h b/deps/hiredis/adapters/libuv.h new file mode 100644 index 000000000..a1967f4fd --- /dev/null +++ b/deps/hiredis/adapters/libuv.h @@ -0,0 +1,121 @@ +#ifndef __HIREDIS_LIBUV_H__ +#define __HIREDIS_LIBUV_H__ +#include <uv.h> +#include "../hiredis.h" +#include "../async.h" +#include <string.h> + +typedef struct redisLibuvEvents { +  redisAsyncContext* context; +  uv_poll_t          handle; +  int                events; +} redisLibuvEvents; + +int redisLibuvAttach(redisAsyncContext*, uv_loop_t*); + +static void redisLibuvPoll(uv_poll_t* handle, int status, int events) { +  redisLibuvEvents* p = (redisLibuvEvents*)handle->data; + +  if (status != 0) { +    return; +  } + +  if (events & UV_READABLE) { +    redisAsyncHandleRead(p->context); +  } +  if (events & UV_WRITABLE) { +    redisAsyncHandleWrite(p->context); +  } +} + + +static void redisLibuvAddRead(void *privdata) { +  redisLibuvEvents* p = (redisLibuvEvents*)privdata; + +  p->events |= UV_READABLE; + +  uv_poll_start(&p->handle, p->events, redisLibuvPoll); +} + + +static void redisLibuvDelRead(void *privdata) { +  redisLibuvEvents* p = (redisLibuvEvents*)privdata; + +  p->events &= ~UV_READABLE; + +  if (p->events) { +    uv_poll_start(&p->handle, p->events, redisLibuvPoll); +  } else { +    uv_poll_stop(&p->handle); +  } +} + + +static void redisLibuvAddWrite(void *privdata) { +  redisLibuvEvents* p = (redisLibuvEvents*)privdata; + +  p->events |= UV_WRITABLE; + +  uv_poll_start(&p->handle, p->events, redisLibuvPoll); +} + + +static void redisLibuvDelWrite(void *privdata) { +  redisLibuvEvents* p = (redisLibuvEvents*)privdata; + +  p->events &= ~UV_WRITABLE; + +  if (p->events) { +    uv_poll_start(&p->handle, p->events, redisLibuvPoll); +  } else { +    uv_poll_stop(&p->handle); +  } +} + + +static void on_close(uv_handle_t* handle) { +  redisLibuvEvents* p = (redisLibuvEvents*)handle->data; + +  free(p); +} + + +static void redisLibuvCleanup(void *privdata) { +  redisLibuvEvents* p = (redisLibuvEvents*)privdata; + +  uv_close((uv_handle_t*)&p->handle, on_close); +} + + +static int redisLibuvAttach(redisAsyncContext* ac, uv_loop_t* loop) { +  redisContext *c = &(ac->c); + +  if (ac->ev.data != NULL) { +    return REDIS_ERR; +  } + +  ac->ev.addRead  = redisLibuvAddRead; +  ac->ev.delRead  = redisLibuvDelRead; +  ac->ev.addWrite = redisLibuvAddWrite; +  ac->ev.delWrite = redisLibuvDelWrite; +  ac->ev.cleanup  = redisLibuvCleanup; + +  redisLibuvEvents* p = (redisLibuvEvents*)malloc(sizeof(*p)); + +  if (!p) { +    return REDIS_ERR; +  } + +  memset(p, 0, sizeof(*p)); + +  if (uv_poll_init(loop, &p->handle, c->fd) != 0) { +    return REDIS_ERR; +  } + +  ac->ev.data    = p; +  p->handle.data = p; +  p->context     = ac; + +  return REDIS_OK; +} +#endif diff --git a/deps/hiredis/async.c b/deps/hiredis/async.c index f65f8694c..f7f343bef 100644 --- a/deps/hiredis/async.c +++ b/deps/hiredis/async.c @@ -62,7 +62,8 @@ void __redisAppendCommand(redisContext *c, char *cmd, size_t len);  /* Functions managing dictionary of callbacks for pub/sub. */  static unsigned int callbackHash(const void *key) { -    return dictGenHashFunction((unsigned char*)key,sdslen((char*)key)); +    return dictGenHashFunction((const unsigned char *)key, +                               sdslen((const sds)key));  }  static void *callbackValDup(void *privdata, const void *src) { @@ -76,8 +77,8 @@ static int callbackKeyCompare(void *privdata, const void *key1, const void *key2      int l1, l2;      ((void) privdata); -    l1 = sdslen((sds)key1); -    l2 = sdslen((sds)key2); +    l1 = sdslen((const sds)key1); +    l2 = sdslen((const sds)key2);      if (l1 != l2) return 0;      return memcmp(key1,key2,l1) == 0;  } @@ -102,7 +103,12 @@ static dictType callbackDict = {  };  static redisAsyncContext *redisAsyncInitialize(redisContext *c) { -    redisAsyncContext *ac = realloc(c,sizeof(redisAsyncContext)); +    redisAsyncContext *ac; + +    ac = realloc(c,sizeof(redisAsyncContext)); +    if (ac == NULL) +        return NULL; +      c = &(ac->c);      /* The regular connect functions will always set the flag REDIS_CONNECTED. @@ -142,15 +148,45 @@ static void __redisAsyncCopyError(redisAsyncContext *ac) {  }  redisAsyncContext *redisAsyncConnect(const char *ip, int port) { -    redisContext *c = redisConnectNonBlock(ip,port); +    redisContext *c; +    redisAsyncContext *ac; + +    c = redisConnectNonBlock(ip,port); +    if (c == NULL) +        return NULL; + +    ac = redisAsyncInitialize(c); +    if (ac == NULL) { +        redisFree(c); +        return NULL; +    } + +    __redisAsyncCopyError(ac); +    return ac; +} + +redisAsyncContext *redisAsyncConnectBind(const char *ip, int port, +                                         const char *source_addr) { +    redisContext *c = redisConnectBindNonBlock(ip,port,source_addr);      redisAsyncContext *ac = redisAsyncInitialize(c);      __redisAsyncCopyError(ac);      return ac;  }  redisAsyncContext *redisAsyncConnectUnix(const char *path) { -    redisContext *c = redisConnectUnixNonBlock(path); -    redisAsyncContext *ac = redisAsyncInitialize(c); +    redisContext *c; +    redisAsyncContext *ac; + +    c = redisConnectUnixNonBlock(path); +    if (c == NULL) +        return NULL; + +    ac = redisAsyncInitialize(c); +    if (ac == NULL) { +        redisFree(c); +        return NULL; +    } +      __redisAsyncCopyError(ac);      return ac;  } @@ -182,6 +218,9 @@ static int __redisPushCallback(redisCallbackList *list, redisCallback *source) {      /* Copy callback from stack to heap */      cb = malloc(sizeof(*cb)); +    if (cb == NULL) +        return REDIS_ERR_OOM; +      if (source != NULL) {          memcpy(cb,source,sizeof(*cb));          cb->next = NULL; @@ -360,7 +399,7 @@ static int __redisGetSubscribeCallback(redisAsyncContext *ac, redisReply *reply,  void redisProcessCallbacks(redisAsyncContext *ac) {      redisContext *c = &(ac->c); -    redisCallback cb; +    redisCallback cb = {NULL, NULL, NULL};      void *reply = NULL;      int status; @@ -372,7 +411,7 @@ void redisProcessCallbacks(redisAsyncContext *ac) {                  __redisAsyncDisconnect(ac);                  return;              } -             +              /* If monitor mode, repush callback */              if(c->flags & REDIS_MONITORING) {                  __redisPushCallback(&ac->replies,&cb); @@ -442,7 +481,7 @@ void redisProcessCallbacks(redisAsyncContext *ac) {  static int __redisAsyncHandleConnect(redisAsyncContext *ac) {      redisContext *c = &(ac->c); -    if (redisCheckSocketError(c,c->fd) == REDIS_ERR) { +    if (redisCheckSocketError(c) == REDIS_ERR) {          /* Try again later when connect(2) is still in progress. */          if (errno == EINPROGRESS)              return REDIS_OK; diff --git a/deps/hiredis/async.h b/deps/hiredis/async.h index 268274e8e..8a2cf1ecd 100644 --- a/deps/hiredis/async.h +++ b/deps/hiredis/async.h @@ -102,6 +102,7 @@ typedef struct redisAsyncContext {  /* Functions that proxy to hiredis */  redisAsyncContext *redisAsyncConnect(const char *ip, int port); +redisAsyncContext *redisAsyncConnectBind(const char *ip, int port, const char *source_addr);  redisAsyncContext *redisAsyncConnectUnix(const char *path);  int redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn);  int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn); diff --git a/deps/hiredis/example-ae.c b/deps/hiredis/examples/example-ae.c index 5ed34a3a6..8efa7306a 100644 --- a/deps/hiredis/example-ae.c +++ b/deps/hiredis/examples/example-ae.c @@ -2,9 +2,10 @@  #include <stdlib.h>  #include <string.h>  #include <signal.h> -#include "hiredis.h" -#include "async.h" -#include "adapters/ae.h" + +#include <hiredis.h> +#include <async.h> +#include <adapters/ae.h>  /* Put event loop in the global scope, so it can be explicitly stopped */  static aeEventLoop *loop; @@ -21,17 +22,22 @@ void getCallback(redisAsyncContext *c, void *r, void *privdata) {  void connectCallback(const redisAsyncContext *c, int status) {      if (status != REDIS_OK) {          printf("Error: %s\n", c->errstr); +        aeStop(loop);          return;      } +      printf("Connected...\n");  }  void disconnectCallback(const redisAsyncContext *c, int status) {      if (status != REDIS_OK) {          printf("Error: %s\n", c->errstr); +        aeStop(loop);          return;      } +      printf("Disconnected...\n"); +    aeStop(loop);  }  int main (int argc, char **argv) { @@ -44,7 +50,7 @@ int main (int argc, char **argv) {          return 1;      } -    loop = aeCreateEventLoop(); +    loop = aeCreateEventLoop(64);      redisAeAttach(loop, c);      redisAsyncSetConnectCallback(c,connectCallback);      redisAsyncSetDisconnectCallback(c,disconnectCallback); diff --git a/deps/hiredis/example-libev.c b/deps/hiredis/examples/example-libev.c index 7894f1f48..cc8b166ec 100644 --- a/deps/hiredis/example-libev.c +++ b/deps/hiredis/examples/example-libev.c @@ -2,9 +2,10 @@  #include <stdlib.h>  #include <string.h>  #include <signal.h> -#include "hiredis.h" -#include "async.h" -#include "adapters/libev.h" + +#include <hiredis.h> +#include <async.h> +#include <adapters/libev.h>  void getCallback(redisAsyncContext *c, void *r, void *privdata) {      redisReply *reply = r; diff --git a/deps/hiredis/example-libevent.c b/deps/hiredis/examples/example-libevent.c index 9da8e02bf..d333c22b7 100644 --- a/deps/hiredis/example-libevent.c +++ b/deps/hiredis/examples/example-libevent.c @@ -2,9 +2,10 @@  #include <stdlib.h>  #include <string.h>  #include <signal.h> -#include "hiredis.h" -#include "async.h" -#include "adapters/libevent.h" + +#include <hiredis.h> +#include <async.h> +#include <adapters/libevent.h>  void getCallback(redisAsyncContext *c, void *r, void *privdata) {      redisReply *reply = r; diff --git a/deps/hiredis/examples/example-libuv.c b/deps/hiredis/examples/example-libuv.c new file mode 100644 index 000000000..a5462d410 --- /dev/null +++ b/deps/hiredis/examples/example-libuv.c @@ -0,0 +1,53 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <signal.h> + +#include <hiredis.h> +#include <async.h> +#include <adapters/libuv.h> + +void getCallback(redisAsyncContext *c, void *r, void *privdata) { +    redisReply *reply = r; +    if (reply == NULL) return; +    printf("argv[%s]: %s\n", (char*)privdata, reply->str); + +    /* Disconnect after receiving the reply to GET */ +    redisAsyncDisconnect(c); +} + +void connectCallback(const redisAsyncContext *c, int status) { +    if (status != REDIS_OK) { +        printf("Error: %s\n", c->errstr); +        return; +    } +    printf("Connected...\n"); +} + +void disconnectCallback(const redisAsyncContext *c, int status) { +    if (status != REDIS_OK) { +        printf("Error: %s\n", c->errstr); +        return; +    } +    printf("Disconnected...\n"); +} + +int main (int argc, char **argv) { +    signal(SIGPIPE, SIG_IGN); +    uv_loop_t* loop = uv_default_loop(); + +    redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); +    if (c->err) { +        /* Let *c leak for now... */ +        printf("Error: %s\n", c->errstr); +        return 1; +    } + +    redisLibuvAttach(c,loop); +    redisAsyncSetConnectCallback(c,connectCallback); +    redisAsyncSetDisconnectCallback(c,disconnectCallback); +    redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc-1], strlen(argv[argc-1])); +    redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key"); +    uv_run(loop, UV_RUN_DEFAULT); +    return 0; +} diff --git a/deps/hiredis/example.c b/deps/hiredis/examples/example.c index 90ff9ed5e..25226a807 100644 --- a/deps/hiredis/example.c +++ b/deps/hiredis/examples/example.c @@ -2,17 +2,24 @@  #include <stdlib.h>  #include <string.h> -#include "hiredis.h" +#include <hiredis.h> -int main(void) { +int main(int argc, char **argv) {      unsigned int j;      redisContext *c;      redisReply *reply; +    const char *hostname = (argc > 1) ? argv[1] : "127.0.0.1"; +    int port = (argc > 2) ? atoi(argv[2]) : 6379;      struct timeval timeout = { 1, 500000 }; // 1.5 seconds -    c = redisConnectWithTimeout((char*)"127.0.0.2", 6379, timeout); -    if (c->err) { -        printf("Connection error: %s\n", c->errstr); +    c = redisConnectWithTimeout(hostname, port, timeout); +    if (c == NULL || c->err) { +        if (c) { +            printf("Connection error: %s\n", c->errstr); +            redisFree(c); +        } else { +            printf("Connection error: can't allocate redis context\n"); +        }          exit(1);      } @@ -27,7 +34,7 @@ int main(void) {      freeReplyObject(reply);      /* Set a key using binary safe API */ -    reply = redisCommand(c,"SET %b %b", "bar", 3, "hello", 5); +    reply = redisCommand(c,"SET %b %b", "bar", (size_t) 3, "hello", (size_t) 5);      printf("SET (binary API): %s\n", reply->str);      freeReplyObject(reply); @@ -64,5 +71,8 @@ int main(void) {      }      freeReplyObject(reply); +    /* Disconnects and frees the context */ +    redisFree(c); +      return 0;  } diff --git a/deps/hiredis/fmacros.h b/deps/hiredis/fmacros.h index 96324eb49..9e5fec0ce 100644 --- a/deps/hiredis/fmacros.h +++ b/deps/hiredis/fmacros.h @@ -13,4 +13,8 @@  #define _XOPEN_SOURCE  #endif +#if __APPLE__ && __MACH__ +#define _OSX +#endif +  #endif diff --git a/deps/hiredis/hiredis.c b/deps/hiredis/hiredis.c index 0b04935a1..2afee5666 100644 --- a/deps/hiredis/hiredis.c +++ b/deps/hiredis/hiredis.c @@ -917,7 +917,7 @@ err:   * %b represents a binary safe string   *   * When using %b you need to provide both the pointer to the string - * and the length in bytes. Examples: + * and the length in bytes as a size_t. Examples:   *   * len = redisFormatCommand(target, "GET %s", mykey);   * len = redisFormatCommand(target, "SET %s %b", mykey, myval, myvallen); @@ -1010,58 +1010,122 @@ void redisFree(redisContext *c) {      free(c);  } +int redisFreeKeepFd(redisContext *c) { +	int fd = c->fd; +	c->fd = -1; +	redisFree(c); +	return fd; +} +  /* Connect to a Redis instance. On error the field error in the returned   * context will be set to the return value of the error function.   * When no set of reply functions is given, the default set will be used. */  redisContext *redisConnect(const char *ip, int port) { -    redisContext *c = redisContextInit(); +    redisContext *c; + +    c = redisContextInit(); +    if (c == NULL) +        return NULL; +      c->flags |= REDIS_BLOCK;      redisContextConnectTcp(c,ip,port,NULL);      return c;  } -redisContext *redisConnectWithTimeout(const char *ip, int port, struct timeval tv) { -    redisContext *c = redisContextInit(); +redisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv) { +    redisContext *c; + +    c = redisContextInit(); +    if (c == NULL) +        return NULL; +      c->flags |= REDIS_BLOCK;      redisContextConnectTcp(c,ip,port,&tv);      return c;  }  redisContext *redisConnectNonBlock(const char *ip, int port) { -    redisContext *c = redisContextInit(); +    redisContext *c; + +    c = redisContextInit(); +    if (c == NULL) +        return NULL; +      c->flags &= ~REDIS_BLOCK;      redisContextConnectTcp(c,ip,port,NULL);      return c;  } -redisContext *redisConnectUnix(const char *path) { +redisContext *redisConnectBindNonBlock(const char *ip, int port, +                                       const char *source_addr) {      redisContext *c = redisContextInit(); +    c->flags &= ~REDIS_BLOCK; +    redisContextConnectBindTcp(c,ip,port,NULL,source_addr); +    return c; +} + +redisContext *redisConnectUnix(const char *path) { +    redisContext *c; + +    c = redisContextInit(); +    if (c == NULL) +        return NULL; +      c->flags |= REDIS_BLOCK;      redisContextConnectUnix(c,path,NULL);      return c;  } -redisContext *redisConnectUnixWithTimeout(const char *path, struct timeval tv) { -    redisContext *c = redisContextInit(); +redisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv) { +    redisContext *c; + +    c = redisContextInit(); +    if (c == NULL) +        return NULL; +      c->flags |= REDIS_BLOCK;      redisContextConnectUnix(c,path,&tv);      return c;  }  redisContext *redisConnectUnixNonBlock(const char *path) { -    redisContext *c = redisContextInit(); +    redisContext *c; + +    c = redisContextInit(); +    if (c == NULL) +        return NULL; +      c->flags &= ~REDIS_BLOCK;      redisContextConnectUnix(c,path,NULL);      return c;  } +redisContext *redisConnectFd(int fd) { +    redisContext *c; + +    c = redisContextInit(); +    if (c == NULL) +        return NULL; + +    c->fd = fd; +    c->flags |= REDIS_BLOCK | REDIS_CONNECTED; +    return c; +} +  /* Set read/write timeout on a blocking socket. */ -int redisSetTimeout(redisContext *c, struct timeval tv) { +int redisSetTimeout(redisContext *c, const struct timeval tv) {      if (c->flags & REDIS_BLOCK)          return redisContextSetTimeout(c,tv);      return REDIS_ERR;  } +/* Enable connection KeepAlive. */ +int redisEnableKeepAlive(redisContext *c) { +    if (redisKeepAlive(c, REDIS_KEEPALIVE_INTERVAL) != REDIS_OK) +        return REDIS_ERR; +    return REDIS_OK; +} +  /* Use this function to handle a read event on the descriptor. It will try   * and read some bytes from the socket and feed them to the reply parser.   * @@ -1077,7 +1141,7 @@ int redisBufferRead(redisContext *c) {      nread = read(c->fd,buf,sizeof(buf));      if (nread == -1) { -        if (errno == EAGAIN && !(c->flags & REDIS_BLOCK)) { +        if ((errno == EAGAIN && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) {              /* Try again later */          } else {              __redisSetError(c,REDIS_ERR_IO,NULL); @@ -1114,7 +1178,7 @@ int redisBufferWrite(redisContext *c, int *done) {      if (sdslen(c->obuf) > 0) {          nwritten = write(c->fd,c->obuf,sdslen(c->obuf));          if (nwritten == -1) { -            if (errno == EAGAIN && !(c->flags & REDIS_BLOCK)) { +            if ((errno == EAGAIN && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) {                  /* Try again later */              } else {                  __redisSetError(c,REDIS_ERR_IO,NULL); @@ -1180,7 +1244,7 @@ int redisGetReply(redisContext *c, void **reply) {   * is used, you need to call redisGetReply yourself to retrieve   * the reply (or replies in pub/sub).   */ -int __redisAppendCommand(redisContext *c, char *cmd, size_t len) { +int __redisAppendCommand(redisContext *c, const char *cmd, size_t len) {      sds newbuf;      newbuf = sdscatlen(c->obuf,cmd,len); @@ -1193,6 +1257,15 @@ int __redisAppendCommand(redisContext *c, char *cmd, size_t len) {      return REDIS_OK;  } +int redisAppendFormattedCommand(redisContext *c, const char *cmd, size_t len) { + +    if (__redisAppendCommand(c, cmd, len) != REDIS_OK) { +        return REDIS_ERR; +    } + +    return REDIS_OK; +} +  int redisvAppendCommand(redisContext *c, const char *format, va_list ap) {      char *cmd;      int len; diff --git a/deps/hiredis/hiredis.h b/deps/hiredis/hiredis.h index b922831e3..7700f4b89 100644 --- a/deps/hiredis/hiredis.h +++ b/deps/hiredis/hiredis.h @@ -36,8 +36,8 @@  #include <sys/time.h> /* for struct timeval */  #define HIREDIS_MAJOR 0 -#define HIREDIS_MINOR 10 -#define HIREDIS_PATCH 1 +#define HIREDIS_MINOR 11 +#define HIREDIS_PATCH 0  #define REDIS_ERR -1  #define REDIS_OK 0 @@ -88,6 +88,8 @@  #define REDIS_READER_MAX_BUF (1024*16)  /* Default max unused reader buffer. */ +#define REDIS_KEEPALIVE_INTERVAL 15 /* seconds */ +  #ifdef __cplusplus  extern "C" {  #endif @@ -171,13 +173,17 @@ typedef struct redisContext {  } redisContext;  redisContext *redisConnect(const char *ip, int port); -redisContext *redisConnectWithTimeout(const char *ip, int port, struct timeval tv); +redisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv);  redisContext *redisConnectNonBlock(const char *ip, int port); +redisContext *redisConnectBindNonBlock(const char *ip, int port, const char *source_addr);  redisContext *redisConnectUnix(const char *path); -redisContext *redisConnectUnixWithTimeout(const char *path, struct timeval tv); +redisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv);  redisContext *redisConnectUnixNonBlock(const char *path); -int redisSetTimeout(redisContext *c, struct timeval tv); +redisContext *redisConnectFd(int fd); +int redisSetTimeout(redisContext *c, const struct timeval tv); +int redisEnableKeepAlive(redisContext *c);  void redisFree(redisContext *c); +int redisFreeKeepFd(redisContext *c);  int redisBufferRead(redisContext *c);  int redisBufferWrite(redisContext *c, int *done); @@ -188,6 +194,10 @@ int redisBufferWrite(redisContext *c, int *done);  int redisGetReply(redisContext *c, void **reply);  int redisGetReplyFromReader(redisContext *c, void **reply); +/* Write a formatted command to the output buffer. Use these functions in blocking mode + * to get a pipeline of commands. */ +int redisAppendFormattedCommand(redisContext *c, const char *cmd, size_t len); +  /* Write a command to the output buffer. Use these functions in blocking mode   * to get a pipeline of commands. */  int redisvAppendCommand(redisContext *c, const char *format, va_list ap); diff --git a/deps/hiredis/net.c b/deps/hiredis/net.c index b10eee2e5..9fe80bba7 100644 --- a/deps/hiredis/net.c +++ b/deps/hiredis/net.c @@ -54,8 +54,15 @@  /* Defined in hiredis.c */  void __redisSetError(redisContext *c, int type, const char *str); +static void redisContextCloseFd(redisContext *c) { +    if (c && c->fd >= 0) { +        close(c->fd); +        c->fd = -1; +    } +} +  static void __redisSetErrorFromErrno(redisContext *c, int type, const char *prefix) { -    char buf[128]; +    char buf[128] = { 0 };      size_t len = 0;      if (prefix != NULL) @@ -64,11 +71,11 @@ static void __redisSetErrorFromErrno(redisContext *c, int type, const char *pref      __redisSetError(c,type,buf);  } -static int redisSetReuseAddr(redisContext *c, int fd) { +static int redisSetReuseAddr(redisContext *c) {      int on = 1; -    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { +    if (setsockopt(c->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {          __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); -        close(fd); +        redisContextCloseFd(c);          return REDIS_ERR;      }      return REDIS_OK; @@ -80,23 +87,24 @@ static int redisCreateSocket(redisContext *c, int type) {          __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);          return REDIS_ERR;      } +    c->fd = s;      if (type == AF_INET) { -        if (redisSetReuseAddr(c,s) == REDIS_ERR) { +        if (redisSetReuseAddr(c) == REDIS_ERR) {              return REDIS_ERR;          }      } -    return s; +    return REDIS_OK;  } -static int redisSetBlocking(redisContext *c, int fd, int blocking) { +static int redisSetBlocking(redisContext *c, int blocking) {      int flags;      /* Set the socket nonblocking.       * Note that fcntl(2) for F_GETFL and F_SETFL can't be       * interrupted by a signal. */ -    if ((flags = fcntl(fd, F_GETFL)) == -1) { +    if ((flags = fcntl(c->fd, F_GETFL)) == -1) {          __redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_GETFL)"); -        close(fd); +        redisContextCloseFd(c);          return REDIS_ERR;      } @@ -105,19 +113,61 @@ static int redisSetBlocking(redisContext *c, int fd, int blocking) {      else          flags |= O_NONBLOCK; -    if (fcntl(fd, F_SETFL, flags) == -1) { +    if (fcntl(c->fd, F_SETFL, flags) == -1) {          __redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_SETFL)"); -        close(fd); +        redisContextCloseFd(c); +        return REDIS_ERR; +    } +    return REDIS_OK; +} + +int redisKeepAlive(redisContext *c, int interval) { +    int val = 1; +    int fd = c->fd; + +    if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1){ +        __redisSetError(c,REDIS_ERR_OTHER,strerror(errno)); +        return REDIS_ERR; +    } + +    val = interval; + +#ifdef _OSX +    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &val, sizeof(val)) < 0) { +        __redisSetError(c,REDIS_ERR_OTHER,strerror(errno)); +        return REDIS_ERR; +    } +#else +#ifndef __sun +    val = interval; +    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val)) < 0) { +        __redisSetError(c,REDIS_ERR_OTHER,strerror(errno)); +        return REDIS_ERR; +    } + +    val = interval/3; +    if (val == 0) val = 1; +    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &val, sizeof(val)) < 0) { +        __redisSetError(c,REDIS_ERR_OTHER,strerror(errno)); +        return REDIS_ERR; +    } + +    val = 3; +    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &val, sizeof(val)) < 0) { +        __redisSetError(c,REDIS_ERR_OTHER,strerror(errno));          return REDIS_ERR;      } +#endif +#endif +      return REDIS_OK;  } -static int redisSetTcpNoDelay(redisContext *c, int fd) { +static int redisSetTcpNoDelay(redisContext *c) {      int yes = 1; -    if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1) { +    if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1) {          __redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(TCP_NODELAY)"); -        close(fd); +        redisContextCloseFd(c);          return REDIS_ERR;      }      return REDIS_OK; @@ -125,18 +175,19 @@ static int redisSetTcpNoDelay(redisContext *c, int fd) {  #define __MAX_MSEC (((LONG_MAX) - 999) / 1000) -static int redisContextWaitReady(redisContext *c, int fd, const struct timeval *timeout) { +static int redisContextWaitReady(redisContext *c, const struct timeval *timeout) {      struct pollfd   wfd[1];      long msec;      msec          = -1; -    wfd[0].fd     = fd; +    wfd[0].fd     = c->fd;      wfd[0].events = POLLOUT;      /* Only use timeout when not NULL. */      if (timeout != NULL) {          if (timeout->tv_usec > 1000000 || timeout->tv_sec > __MAX_MSEC) { -            close(fd); +            __redisSetErrorFromErrno(c, REDIS_ERR_IO, NULL); +            redisContextCloseFd(c);              return REDIS_ERR;          } @@ -152,47 +203,45 @@ static int redisContextWaitReady(redisContext *c, int fd, const struct timeval *          if ((res = poll(wfd, 1, msec)) == -1) {              __redisSetErrorFromErrno(c, REDIS_ERR_IO, "poll(2)"); -            close(fd); +            redisContextCloseFd(c);              return REDIS_ERR;          } else if (res == 0) {              errno = ETIMEDOUT;              __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); -            close(fd); +            redisContextCloseFd(c);              return REDIS_ERR;          } -        if (redisCheckSocketError(c, fd) != REDIS_OK) +        if (redisCheckSocketError(c) != REDIS_OK)              return REDIS_ERR;          return REDIS_OK;      }      __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); -    close(fd); +    redisContextCloseFd(c);      return REDIS_ERR;  } -int redisCheckSocketError(redisContext *c, int fd) { +int redisCheckSocketError(redisContext *c) {      int err = 0;      socklen_t errlen = sizeof(err); -    if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) { +    if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {          __redisSetErrorFromErrno(c,REDIS_ERR_IO,"getsockopt(SO_ERROR)"); -        close(fd);          return REDIS_ERR;      }      if (err) {          errno = err;          __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); -        close(fd);          return REDIS_ERR;      }      return REDIS_OK;  } -int redisContextSetTimeout(redisContext *c, struct timeval tv) { +int redisContextSetTimeout(redisContext *c, const struct timeval tv) {      if (setsockopt(c->fd,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv)) == -1) {          __redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(SO_RCVTIMEO)");          return REDIS_ERR; @@ -204,10 +253,12 @@ int redisContextSetTimeout(redisContext *c, struct timeval tv) {      return REDIS_OK;  } -int redisContextConnectTcp(redisContext *c, const char *addr, int port, struct timeval *timeout) { +static int _redisContextConnectTcp(redisContext *c, const char *addr, int port, +                                   const struct timeval *timeout, +                                   const char *source_addr) {      int s, rv;      char _port[6];  /* strlen("65535"); */ -    struct addrinfo hints, *servinfo, *p; +    struct addrinfo hints, *servinfo, *bservinfo, *p, *b;      int blocking = (c->flags & REDIS_BLOCK);      snprintf(_port, 6, "%d", port); @@ -231,25 +282,47 @@ int redisContextConnectTcp(redisContext *c, const char *addr, int port, struct t          if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1)              continue; -        if (redisSetBlocking(c,s,0) != REDIS_OK) +        c->fd = s; +        if (redisSetBlocking(c,0) != REDIS_OK)              goto error; +        if (source_addr) { +            int bound = 0; +            /* Using getaddrinfo saves us from self-determining IPv4 vs IPv6 */ +            if ((rv = getaddrinfo(source_addr, NULL, &hints, &bservinfo)) != 0) { +                char buf[128]; +                snprintf(buf,sizeof(buf),"Can't get addr: %s",gai_strerror(rv)); +                __redisSetError(c,REDIS_ERR_OTHER,buf); +                goto error; +            } +            for (b = bservinfo; b != NULL; b = b->ai_next) { +                if (bind(s,b->ai_addr,b->ai_addrlen) != -1) { +                    bound = 1; +                    break; +                } +            } +            if (!bound) { +                char buf[128]; +                snprintf(buf,sizeof(buf),"Can't bind socket: %s",strerror(errno)); +                __redisSetError(c,REDIS_ERR_OTHER,buf); +                goto error; +            } +        }          if (connect(s,p->ai_addr,p->ai_addrlen) == -1) {              if (errno == EHOSTUNREACH) { -                close(s); +                redisContextCloseFd(c);                  continue;              } else if (errno == EINPROGRESS && !blocking) {                  /* This is ok. */              } else { -                if (redisContextWaitReady(c,s,timeout) != REDIS_OK) +                if (redisContextWaitReady(c,timeout) != REDIS_OK)                      goto error;              }          } -        if (blocking && redisSetBlocking(c,s,1) != REDIS_OK) +        if (blocking && redisSetBlocking(c,1) != REDIS_OK)              goto error; -        if (redisSetTcpNoDelay(c,s) != REDIS_OK) +        if (redisSetTcpNoDelay(c) != REDIS_OK)              goto error; -        c->fd = s;          c->flags |= REDIS_CONNECTED;          rv = REDIS_OK;          goto end; @@ -268,32 +341,41 @@ end:      return rv;  // Need to return REDIS_OK if alright  } -int redisContextConnectUnix(redisContext *c, const char *path, struct timeval *timeout) { -    int s; +int redisContextConnectTcp(redisContext *c, const char *addr, int port, +                           const struct timeval *timeout) { +    return _redisContextConnectTcp(c, addr, port, timeout, NULL); +} + +int redisContextConnectBindTcp(redisContext *c, const char *addr, int port, +                               const struct timeval *timeout, +                               const char *source_addr) { +    return _redisContextConnectTcp(c, addr, port, timeout, source_addr); +} + +int redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout) {      int blocking = (c->flags & REDIS_BLOCK);      struct sockaddr_un sa; -    if ((s = redisCreateSocket(c,AF_LOCAL)) < 0) +    if (redisCreateSocket(c,AF_LOCAL) < 0)          return REDIS_ERR; -    if (redisSetBlocking(c,s,0) != REDIS_OK) +    if (redisSetBlocking(c,0) != REDIS_OK)          return REDIS_ERR;      sa.sun_family = AF_LOCAL;      strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1); -    if (connect(s, (struct sockaddr*)&sa, sizeof(sa)) == -1) { +    if (connect(c->fd, (struct sockaddr*)&sa, sizeof(sa)) == -1) {          if (errno == EINPROGRESS && !blocking) {              /* This is ok. */          } else { -            if (redisContextWaitReady(c,s,timeout) != REDIS_OK) +            if (redisContextWaitReady(c,timeout) != REDIS_OK)                  return REDIS_ERR;          }      }      /* Reset socket to be blocking after connect(2). */ -    if (blocking && redisSetBlocking(c,s,1) != REDIS_OK) +    if (blocking && redisSetBlocking(c,1) != REDIS_OK)          return REDIS_ERR; -    c->fd = s;      c->flags |= REDIS_CONNECTED;      return REDIS_OK;  } diff --git a/deps/hiredis/net.h b/deps/hiredis/net.h index eb8a0a1cf..5e742f577 100644 --- a/deps/hiredis/net.h +++ b/deps/hiredis/net.h @@ -39,9 +39,13 @@  #define AF_LOCAL AF_UNIX  #endif -int redisCheckSocketError(redisContext *c, int fd); -int redisContextSetTimeout(redisContext *c, struct timeval tv); -int redisContextConnectTcp(redisContext *c, const char *addr, int port, struct timeval *timeout); -int redisContextConnectUnix(redisContext *c, const char *path, struct timeval *timeout); +int redisCheckSocketError(redisContext *c); +int redisContextSetTimeout(redisContext *c, const struct timeval tv); +int redisContextConnectTcp(redisContext *c, const char *addr, int port, const struct timeval *timeout); +int redisContextConnectBindTcp(redisContext *c, const char *addr, int port, +                               const struct timeval *timeout, +                               const char *source_addr); +int redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout); +int redisKeepAlive(redisContext *c, int interval);  #endif diff --git a/deps/hiredis/sds.c b/deps/hiredis/sds.c index d66c1d730..5306f1ffb 100644 --- a/deps/hiredis/sds.c +++ b/deps/hiredis/sds.c @@ -1,6 +1,6 @@ -/* SDSLib, A C dynamic strings library +/* SDS (Simple Dynamic Strings), A C dynamic strings library.   * - * Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com> + * Copyright (c) 2006-2014, Salvatore Sanfilippo <antirez at gmail dot com>   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -33,8 +33,8 @@  #include <string.h>  #include <ctype.h>  #include <assert.h> +  #include "sds.h" -#include "zmalloc.h"  /* Create a new sds string with the content specified by the 'init' pointer   * and 'initlen'. @@ -52,9 +52,9 @@ sds sdsnewlen(const void *init, size_t initlen) {      struct sdshdr *sh;      if (init) { -        sh = zmalloc(sizeof(struct sdshdr)+initlen+1); +        sh = malloc(sizeof *sh+initlen+1);      } else { -        sh = zcalloc(sizeof(struct sdshdr)+initlen+1); +        sh = calloc(sizeof *sh+initlen+1,1);      }      if (sh == NULL) return NULL;      sh->len = initlen; @@ -85,7 +85,7 @@ sds sdsdup(const sds s) {  /* Free an sds string. No operation is performed if 's' is NULL. */  void sdsfree(sds s) {      if (s == NULL) return; -    zfree(s-sizeof(struct sdshdr)); +    free(s-sizeof(struct sdshdr));  }  /* Set the sds string length to the length as obtained with strlen(), so @@ -103,7 +103,7 @@ void sdsfree(sds s) {   * the output will be "6" as the string was modified but the logical length   * remains 6 bytes. */  void sdsupdatelen(sds s) { -    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr))); +    struct sdshdr *sh = (void*) (s-sizeof *sh);;      int reallen = strlen(s);      sh->free += (sh->len-reallen);      sh->len = reallen; @@ -114,7 +114,7 @@ void sdsupdatelen(sds s) {   * so that next append operations will not require allocations up to the   * number of bytes previously available. */  void sdsclear(sds s) { -    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr))); +    struct sdshdr *sh = (void*) (s-sizeof *sh);;      sh->free += sh->len;      sh->len = 0;      sh->buf[0] = '\0'; @@ -133,13 +133,13 @@ sds sdsMakeRoomFor(sds s, size_t addlen) {      if (free >= addlen) return s;      len = sdslen(s); -    sh = (void*) (s-(sizeof(struct sdshdr))); +    sh = (void*) (s-sizeof *sh);;      newlen = (len+addlen);      if (newlen < SDS_MAX_PREALLOC)          newlen *= 2;      else          newlen += SDS_MAX_PREALLOC; -    newsh = zrealloc(sh, sizeof(struct sdshdr)+newlen+1); +    newsh = realloc(sh, sizeof *newsh+newlen+1);      if (newsh == NULL) return NULL;      newsh->free = newlen - len; @@ -155,8 +155,8 @@ sds sdsMakeRoomFor(sds s, size_t addlen) {  sds sdsRemoveFreeSpace(sds s) {      struct sdshdr *sh; -    sh = (void*) (s-(sizeof(struct sdshdr))); -    sh = zrealloc(sh, sizeof(struct sdshdr)+sh->len+1); +    sh = (void*) (s-sizeof *sh);; +    sh = realloc(sh, sizeof *sh+sh->len+1);      sh->free = 0;      return sh->buf;  } @@ -169,7 +169,7 @@ sds sdsRemoveFreeSpace(sds s) {   * 4) The implicit null term.   */  size_t sdsAllocSize(sds s) { -    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr))); +    struct sdshdr *sh = (void*) (s-sizeof *sh);;      return sizeof(*sh)+sh->len+sh->free+1;  } @@ -198,7 +198,7 @@ size_t sdsAllocSize(sds s) {   * sdsIncrLen(s, nread);   */  void sdsIncrLen(sds s, int incr) { -    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr))); +    struct sdshdr *sh = (void*) (s-sizeof *sh);;      assert(sh->free >= incr);      sh->len += incr; @@ -213,7 +213,7 @@ void sdsIncrLen(sds s, int incr) {   * if the specified length is smaller than the current length, no operation   * is performed. */  sds sdsgrowzero(sds s, size_t len) { -    struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr))); +    struct sdshdr *sh = (void*) (s-sizeof *sh);      size_t totlen, curlen = sh->len;      if (len <= curlen) return s; @@ -221,7 +221,7 @@ sds sdsgrowzero(sds s, size_t len) {      if (s == NULL) return NULL;      /* Make sure added region doesn't contain garbage */ -    sh = (void*)(s-(sizeof(struct sdshdr))); +    sh = (void*)(s-sizeof *sh);      memset(s+curlen,0,(len-curlen+1)); /* also set trailing \0 byte */      totlen = sh->len+sh->free;      sh->len = len; @@ -240,7 +240,7 @@ sds sdscatlen(sds s, const void *t, size_t len) {      s = sdsMakeRoomFor(s,len);      if (s == NULL) return NULL; -    sh = (void*) (s-(sizeof(struct sdshdr))); +    sh = (void*) (s-sizeof *sh);;      memcpy(s+curlen, t, len);      sh->len = curlen+len;      sh->free = sh->free-len; @@ -267,13 +267,13 @@ sds sdscatsds(sds s, const sds t) {  /* Destructively modify the sds string 's' to hold the specified binary   * safe string pointed by 't' of length 'len' bytes. */  sds sdscpylen(sds s, const char *t, size_t len) { -    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr))); +    struct sdshdr *sh = (void*) (s-sizeof *sh);;      size_t totlen = sh->free+sh->len;      if (totlen < len) {          s = sdsMakeRoomFor(s,len-sh->len);          if (s == NULL) return NULL; -        sh = (void*) (s-(sizeof(struct sdshdr))); +        sh = (void*) (s-sizeof *sh);;          totlen = sh->free+sh->len;      }      memcpy(s, t, len); @@ -296,20 +296,20 @@ sds sdscatvprintf(sds s, const char *fmt, va_list ap) {      size_t buflen = 16;      while(1) { -        buf = zmalloc(buflen); +        buf = malloc(buflen);          if (buf == NULL) return NULL;          buf[buflen-2] = '\0';          va_copy(cpy,ap);          vsnprintf(buf, buflen, fmt, cpy);          if (buf[buflen-2] != '\0') { -            zfree(buf); +            free(buf);              buflen *= 2;              continue;          }          break;      }      t = sdscat(s, buf); -    zfree(buf); +    free(buf);      return t;  } @@ -352,8 +352,8 @@ sds sdscatprintf(sds s, const char *fmt, ...) {   *   * Output will be just "Hello World".   */ -sds sdstrim(sds s, const char *cset) { -    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr))); +void sdstrim(sds s, const char *cset) { +    struct sdshdr *sh = (void*) (s-sizeof *sh);;      char *start, *end, *sp, *ep;      size_t len; @@ -366,7 +366,6 @@ sds sdstrim(sds s, const char *cset) {      sh->buf[len] = '\0';      sh->free = sh->free+(sh->len-len);      sh->len = len; -    return s;  }  /* Turn the string into a smaller (or equal) string containing only the @@ -383,10 +382,10 @@ sds sdstrim(sds s, const char *cset) {   * Example:   *   * s = sdsnew("Hello World"); - * sdstrim(s,1,-1); => "ello Worl" + * sdsrange(s,1,-1); => "ello World"   */  void sdsrange(sds s, int start, int end) { -    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr))); +    struct sdshdr *sh = (void*) (s-sizeof *sh);;      size_t newlen, len = sdslen(s);      if (len == 0) return; @@ -474,7 +473,7 @@ sds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count      if (seplen < 1 || len < 0) return NULL; -    tokens = zmalloc(sizeof(sds)*slots); +    tokens = malloc(sizeof(sds)*slots);      if (tokens == NULL) return NULL;      if (len == 0) { @@ -487,7 +486,7 @@ sds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count              sds *newtokens;              slots *= 2; -            newtokens = zrealloc(tokens,sizeof(sds)*slots); +            newtokens = realloc(tokens,sizeof(sds)*slots);              if (newtokens == NULL) goto cleanup;              tokens = newtokens;          } @@ -511,7 +510,7 @@ cleanup:      {          int i;          for (i = 0; i < elements; i++) sdsfree(tokens[i]); -        zfree(tokens); +        free(tokens);          *count = 0;          return NULL;      } @@ -522,7 +521,7 @@ void sdsfreesplitres(sds *tokens, int count) {      if (!tokens) return;      while(count--)          sdsfree(tokens[count]); -    zfree(tokens); +    free(tokens);  }  /* Create an sds string from a long long value. It is much faster than: @@ -582,7 +581,7 @@ int is_hex_digit(char c) {             (c >= 'A' && c <= 'F');  } -/* Helper function for sdssplitargs() that converts an hex digit into an +/* Helper function for sdssplitargs() that converts a hex digit into an   * integer from 0 to 15 */  int hex_digit_to_int(char c) {      switch(c) { @@ -715,13 +714,13 @@ sds *sdssplitargs(const char *line, int *argc) {                  if (*p) p++;              }              /* add the token to the vector */ -            vector = zrealloc(vector,((*argc)+1)*sizeof(char*)); +            vector = realloc(vector,((*argc)+1)*sizeof(char*));              vector[*argc] = current;              (*argc)++;              current = NULL;          } else {              /* Even on empty input string return something not NULL. */ -            if (vector == NULL) vector = zmalloc(sizeof(void*)); +            if (vector == NULL) vector = malloc(sizeof(void*));              return vector;          }      } @@ -729,7 +728,7 @@ sds *sdssplitargs(const char *line, int *argc) {  err:      while((*argc)--)          sdsfree(vector[*argc]); -    zfree(vector); +    free(vector);      if (current) sdsfree(current);      *argc = 0;      return NULL; @@ -760,13 +759,25 @@ sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen) {  /* Join an array of C strings using the specified separator (also a C string).   * Returns the result as an sds string. */ -sds sdsjoin(char **argv, int argc, char *sep) { +sds sdsjoin(char **argv, int argc, char *sep, size_t seplen) {      sds join = sdsempty();      int j;      for (j = 0; j < argc; j++) {          join = sdscat(join, argv[j]); -        if (j != argc-1) join = sdscat(join,sep); +        if (j != argc-1) join = sdscatlen(join,sep,seplen); +    } +    return join; +} + +/* Like sdsjoin, but joins an array of SDS strings. */ +sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen) { +    sds join = sdsempty(); +    int j; + +    for (j = 0; j < argc; j++) { +        join = sdscatsds(join, argv[j]); +        if (j != argc-1) join = sdscatlen(join,sep,seplen);      }      return join;  } @@ -807,36 +818,43 @@ int main(void) {              sdslen(x) == 3 && memcmp(x,"123\0",4) ==0)          sdsfree(x); -        x = sdstrim(sdsnew("xxciaoyyy"),"xy"); +        x = sdsnew("xxciaoyyy"); +        sdstrim(x,"xy");          test_cond("sdstrim() correctly trims characters",              sdslen(x) == 4 && memcmp(x,"ciao\0",5) == 0) -        y = sdsrange(sdsdup(x),1,1); +        y = sdsdup(x); +        sdsrange(y,1,1);          test_cond("sdsrange(...,1,1)",              sdslen(y) == 1 && memcmp(y,"i\0",2) == 0)          sdsfree(y); -        y = sdsrange(sdsdup(x),1,-1); +        y = sdsdup(x); +        sdsrange(y,1,-1);          test_cond("sdsrange(...,1,-1)",              sdslen(y) == 3 && memcmp(y,"iao\0",4) == 0)          sdsfree(y); -        y = sdsrange(sdsdup(x),-2,-1); +        y = sdsdup(x); +        sdsrange(y,-2,-1);          test_cond("sdsrange(...,-2,-1)",              sdslen(y) == 2 && memcmp(y,"ao\0",3) == 0)          sdsfree(y); -        y = sdsrange(sdsdup(x),2,1); +        y = sdsdup(x); +        sdsrange(y,2,1);          test_cond("sdsrange(...,2,1)",              sdslen(y) == 0 && memcmp(y,"\0",1) == 0)          sdsfree(y); -        y = sdsrange(sdsdup(x),1,100); +        y = sdsdup(x); +        sdsrange(y,1,100);          test_cond("sdsrange(...,1,100)",              sdslen(y) == 3 && memcmp(y,"iao\0",4) == 0)          sdsfree(y); -        y = sdsrange(sdsdup(x),100,100); +        y = sdsdup(x); +        sdsrange(y,100,100);          test_cond("sdsrange(...,100,100)",              sdslen(y) == 0 && memcmp(y,"\0",1) == 0) @@ -858,6 +876,13 @@ int main(void) {          y = sdsnew("bar");          test_cond("sdscmp(bar,bar)", sdscmp(x,y) < 0) +        sdsfree(y); +        sdsfree(x); +        x = sdsnewlen("\a\n\0foo\r",7); +        y = sdscatrepr(sdsempty(),x,sdslen(x)); +        test_cond("sdscatrepr(...data...)", +            memcmp(y,"\"\\a\\n\\x00foo\\r\"",15) == 0) +          {              int oldfree; diff --git a/deps/hiredis/sds.h b/deps/hiredis/sds.h index 615c751cd..ab6fc9c05 100644 --- a/deps/hiredis/sds.h +++ b/deps/hiredis/sds.h @@ -1,6 +1,6 @@ -/* SDSLib, A C dynamic strings library +/* SDS (Simple Dynamic Strings), A C dynamic strings library.   * - * Copyright (c) 2006-2010, Salvatore Sanfilippo <antirez at gmail dot com> + * Copyright (c) 2006-2014, Salvatore Sanfilippo <antirez at gmail dot com>   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -45,12 +45,12 @@ struct sdshdr {  };  static inline size_t sdslen(const sds s) { -    struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr))); +    struct sdshdr *sh = (void*)(s-sizeof *sh);      return sh->len;  }  static inline size_t sdsavail(const sds s) { -    struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr))); +    struct sdshdr *sh = (void*)(s-sizeof *sh);      return sh->free;  } @@ -76,7 +76,7 @@ sds sdscatprintf(sds s, const char *fmt, ...)  sds sdscatprintf(sds s, const char *fmt, ...);  #endif -sds sdstrim(sds s, const char *cset); +void sdstrim(sds s, const char *cset);  void sdsrange(sds s, int start, int end);  void sdsupdatelen(sds s);  void sdsclear(sds s); @@ -89,7 +89,8 @@ sds sdsfromlonglong(long long value);  sds sdscatrepr(sds s, const char *p, size_t len);  sds *sdssplitargs(const char *line, int *argc);  sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen); -sds sdsjoin(char **argv, int argc, char *sep); +sds sdsjoin(char **argv, int argc, char *sep, size_t seplen); +sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen);  /* Low level functions exposed to the user API */  sds sdsMakeRoomFor(sds s, size_t addlen); diff --git a/deps/hiredis/test.c b/deps/hiredis/test.c index 5945b6552..713cc06c5 100644 --- a/deps/hiredis/test.c +++ b/deps/hiredis/test.c @@ -8,12 +8,14 @@  #include <unistd.h>  #include <signal.h>  #include <errno.h> +#include <limits.h>  #include "hiredis.h"  enum connection_type {      CONN_TCP, -    CONN_UNIX +    CONN_UNIX, +    CONN_FD  };  struct config { @@ -22,6 +24,7 @@ struct config {      struct {          const char *host;          int port; +        struct timeval timeout;      } tcp;      struct { @@ -62,7 +65,7 @@ static redisContext *select_database(redisContext *c) {      return c;  } -static void disconnect(redisContext *c) { +static int disconnect(redisContext *c, int keep_fd) {      redisReply *reply;      /* Make sure we're on DB 9. */ @@ -73,8 +76,11 @@ static void disconnect(redisContext *c) {      assert(reply != NULL);      freeReplyObject(reply); -    /* Free the context as well. */ +    /* Free the context as well, but keep the fd if requested. */ +    if (keep_fd) +        return redisFreeKeepFd(c);      redisFree(c); +    return -1;  }  static redisContext *connect(struct config config) { @@ -84,11 +90,22 @@ static redisContext *connect(struct config config) {          c = redisConnect(config.tcp.host, config.tcp.port);      } else if (config.type == CONN_UNIX) {          c = redisConnectUnix(config.unix.path); +    } else if (config.type == CONN_FD) { +        /* Create a dummy connection just to get an fd to inherit */ +        redisContext *dummy_ctx = redisConnectUnix(config.unix.path); +        if (dummy_ctx) { +            int fd = disconnect(dummy_ctx, 1); +            printf("Connecting to inherited fd %d\n", fd); +            c = redisConnectFd(fd); +        }      } else {          assert(NULL);      } -    if (c->err) { +    if (c == NULL) { +        printf("Connection error: can't allocate redis context\n"); +        exit(1); +    } else if (c->err) {          printf("Connection error: %s\n", c->errstr);          exit(1);      } @@ -125,13 +142,13 @@ static void test_format_commands(void) {      free(cmd);      test("Format command with %%b string interpolation: "); -    len = redisFormatCommand(&cmd,"SET %b %b","foo",3,"b\0r",3); +    len = redisFormatCommand(&cmd,"SET %b %b","foo",(size_t)3,"b\0r",(size_t)3);      test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nb\0r\r\n",len) == 0 &&          len == 4+4+(3+2)+4+(3+2)+4+(3+2));      free(cmd);      test("Format command with %%b and an empty string: "); -    len = redisFormatCommand(&cmd,"SET %b %b","foo",3,"",0); +    len = redisFormatCommand(&cmd,"SET %b %b","foo",(size_t)3,"",(size_t)0);      test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$0\r\n\r\n",len) == 0 &&          len == 4+4+(3+2)+4+(3+2)+4+(0+2));      free(cmd); @@ -177,7 +194,7 @@ static void test_format_commands(void) {      FLOAT_WIDTH_TEST(double);      test("Format command with invalid printf format: "); -    len = redisFormatCommand(&cmd,"key:%08p %b",(void*)1234,"foo",3); +    len = redisFormatCommand(&cmd,"key:%08p %b",(void*)1234,"foo",(size_t)3);      test_cond(len == -1);      const char *argv[3]; @@ -200,10 +217,33 @@ static void test_format_commands(void) {      free(cmd);  } +static void test_append_formatted_commands(struct config config) { +    redisContext *c; +    redisReply *reply; +    char *cmd; +    int len; + +    c = connect(config); + +    test("Append format command: "); + +    len = redisFormatCommand(&cmd, "SET foo bar"); + +    test_cond(redisAppendFormattedCommand(c, cmd, len) == REDIS_OK); + +    assert(redisGetReply(c, (void*)&reply) == REDIS_OK); + +    free(cmd); +    freeReplyObject(reply); + +    disconnect(c, 0); +} +  static void test_reply_reader(void) {      redisReader *reader;      void *reply;      int ret; +    int i;      test("Error handling in reply parser: ");      reader = redisReaderCreate(); @@ -225,12 +265,13 @@ static void test_reply_reader(void) {                strcasecmp(reader->errstr,"Protocol error, got \"@\" as reply type byte") == 0);      redisReaderFree(reader); -    test("Set error on nested multi bulks with depth > 2: "); +    test("Set error on nested multi bulks with depth > 7: ");      reader = redisReaderCreate(); -    redisReaderFeed(reader,(char*)"*1\r\n",4); -    redisReaderFeed(reader,(char*)"*1\r\n",4); -    redisReaderFeed(reader,(char*)"*1\r\n",4); -    redisReaderFeed(reader,(char*)"*1\r\n",4); + +    for (i = 0; i < 9; i++) { +        redisReaderFeed(reader,(char*)"*1\r\n",4); +    } +      ret = redisReaderGetReply(reader,NULL);      test_cond(ret == REDIS_ERR &&                strncasecmp(reader->errstr,"No support for",14) == 0); @@ -284,7 +325,10 @@ static void test_blocking_connection_errors(void) {      c = redisConnect((char*)"idontexist.local", 6379);      test_cond(c->err == REDIS_ERR_OTHER &&          (strcmp(c->errstr,"Name or service not known") == 0 || -         strcmp(c->errstr,"Can't resolve: idontexist.local") == 0)); +         strcmp(c->errstr,"Can't resolve: idontexist.local") == 0 || +         strcmp(c->errstr,"nodename nor servname provided, or not known") == 0 || +         strcmp(c->errstr,"No address associated with hostname") == 0 || +         strcmp(c->errstr,"no address associated with name") == 0));      redisFree(c);      test("Returns error when the port is not open: "); @@ -326,7 +370,7 @@ static void test_blocking_connection(struct config config) {      freeReplyObject(reply);      test("%%b String interpolation works: "); -    reply = redisCommand(c,"SET %b %b","foo",3,"hello\x00world",11); +    reply = redisCommand(c,"SET %b %b","foo",(size_t)3,"hello\x00world",(size_t)11);      freeReplyObject(reply);      reply = redisCommand(c,"GET foo");      test_cond(reply->type == REDIS_REPLY_STRING && @@ -374,7 +418,7 @@ static void test_blocking_connection(struct config config) {                strcasecmp(reply->element[1]->str,"pong") == 0);      freeReplyObject(reply); -    disconnect(c); +    disconnect(c, 0);  }  static void test_blocking_io_errors(struct config config) { @@ -428,6 +472,30 @@ static void test_blocking_io_errors(struct config config) {      redisFree(c);  } +static void test_invalid_timeout_errors(struct config config) { +    redisContext *c; + +    test("Set error when an invalid timeout usec value is given to redisConnectWithTimeout: "); + +    config.tcp.timeout.tv_sec = 0; +    config.tcp.timeout.tv_usec = 10000001; + +    c = redisConnectWithTimeout(config.tcp.host, config.tcp.port, config.tcp.timeout); + +    test_cond(c->err == REDIS_ERR_IO); + +    test("Set error when an invalid timeout sec value is given to redisConnectWithTimeout: "); + +    config.tcp.timeout.tv_sec = (((LONG_MAX) - 999) / 1000) + 1; +    config.tcp.timeout.tv_usec = 0; + +    c = redisConnectWithTimeout(config.tcp.host, config.tcp.port, config.tcp.timeout); + +    test_cond(c->err == REDIS_ERR_IO); + +    redisFree(c); +} +  static void test_throughput(struct config config) {      redisContext *c = connect(config);      redisReply **replies; @@ -490,7 +558,7 @@ static void test_throughput(struct config config) {      free(replies);      printf("\t(%dx LRANGE with 500 elements (pipelined): %.3fs)\n", num, (t2-t1)/1000000.0); -    disconnect(c); +    disconnect(c, 0);  }  // static long __test_callback_flags = 0; @@ -603,6 +671,7 @@ int main(int argc, char **argv) {          }      };      int throughput = 1; +    int test_inherit_fd = 1;      /* Ignore broken pipe signal (for I/O error tests). */      signal(SIGPIPE, SIG_IGN); @@ -621,6 +690,8 @@ int main(int argc, char **argv) {              cfg.unix.path = argv[0];          } else if (argc >= 1 && !strcmp(argv[0],"--skip-throughput")) {              throughput = 0; +        } else if (argc >= 1 && !strcmp(argv[0],"--skip-inherit-fd")) { +            test_inherit_fd = 0;          } else {              fprintf(stderr, "Invalid argument: %s\n", argv[0]);              exit(1); @@ -636,6 +707,8 @@ int main(int argc, char **argv) {      cfg.type = CONN_TCP;      test_blocking_connection(cfg);      test_blocking_io_errors(cfg); +    test_invalid_timeout_errors(cfg); +    test_append_formatted_commands(cfg);      if (throughput) test_throughput(cfg);      printf("\nTesting against Unix socket connection (%s):\n", cfg.unix.path); @@ -644,6 +717,12 @@ int main(int argc, char **argv) {      test_blocking_io_errors(cfg);      if (throughput) test_throughput(cfg); +    if (test_inherit_fd) { +        printf("\nTesting against inherited fd (%s):\n", cfg.unix.path); +        cfg.type = CONN_FD; +        test_blocking_connection(cfg); +    } +      if (fails) {          printf("*** %d TESTS FAILED ***\n", fails);          return 1; diff --git a/deps/hiredis/zmalloc.h b/deps/hiredis/zmalloc.h deleted file mode 100644 index 99b87ace9..000000000 --- a/deps/hiredis/zmalloc.h +++ /dev/null @@ -1,13 +0,0 @@ -/* Drop in replacement for zmalloc.h in order to just use libc malloc without - * any wrappering. */ - -#ifndef ZMALLOC_H -#define ZMALLOC_H - -#define zmalloc malloc -#define zrealloc realloc -#define zcalloc(x) calloc(x,1) -#define zfree free -#define zstrdup strdup - -#endif  | 
