Commit 0ee7c668 authored by Pieter Noordhuis's avatar Pieter Noordhuis
Browse files

Use static buffer for error string on context

parent 7f113606
...@@ -828,14 +828,19 @@ int redisFormatCommandArgv(char **target, int argc, const char **argv, const siz ...@@ -828,14 +828,19 @@ int redisFormatCommandArgv(char **target, int argc, const char **argv, const siz
return totlen; return totlen;
} }
void __redisSetError(redisContext *c, int type, const sds errstr) { void __redisSetError(redisContext *c, int type, const char *str) {
size_t len;
c->err = type; c->err = type;
if (errstr != NULL) { if (str != NULL) {
c->errstr = errstr; len = strlen(str);
len = len < (sizeof(c->errstr)-1) ? len : (sizeof(c->errstr)-1);
memcpy(c->errstr,str,len);
c->errstr[len] = '\0';
} else { } else {
/* Only REDIS_ERR_IO may lack a description! */ /* Only REDIS_ERR_IO may lack a description! */
assert(type == REDIS_ERR_IO); assert(type == REDIS_ERR_IO);
c->errstr = sdsnew(strerror(errno)); strerror_r(errno,c->errstr,sizeof(c->errstr));
} }
} }
...@@ -847,7 +852,7 @@ static redisContext *redisContextInit(void) { ...@@ -847,7 +852,7 @@ static redisContext *redisContextInit(void) {
return NULL; return NULL;
c->err = 0; c->err = 0;
c->errstr = NULL; c->errstr[0] = '\0';
c->obuf = sdsempty(); c->obuf = sdsempty();
c->reader = redisReplyReaderCreate(); c->reader = redisReplyReaderCreate();
return c; return c;
...@@ -856,8 +861,6 @@ static redisContext *redisContextInit(void) { ...@@ -856,8 +861,6 @@ static redisContext *redisContextInit(void) {
void redisFree(redisContext *c) { void redisFree(redisContext *c) {
if (c->fd > 0) if (c->fd > 0)
close(c->fd); close(c->fd);
if (c->errstr != NULL)
sdsfree(c->errstr);
if (c->obuf != NULL) if (c->obuf != NULL)
sdsfree(c->obuf); sdsfree(c->obuf);
if (c->reader != NULL) if (c->reader != NULL)
...@@ -933,8 +936,7 @@ int redisBufferRead(redisContext *c) { ...@@ -933,8 +936,7 @@ int redisBufferRead(redisContext *c) {
return REDIS_ERR; return REDIS_ERR;
} }
} else if (nread == 0) { } else if (nread == 0) {
__redisSetError(c,REDIS_ERR_EOF, __redisSetError(c,REDIS_ERR_EOF,"Server closed the connection");
sdsnew("Server closed the connection"));
return REDIS_ERR; return REDIS_ERR;
} else { } else {
redisReplyReaderFeed(c->reader,buf,nread); redisReplyReaderFeed(c->reader,buf,nread);
...@@ -979,8 +981,7 @@ int redisBufferWrite(redisContext *c, int *done) { ...@@ -979,8 +981,7 @@ int redisBufferWrite(redisContext *c, int *done) {
* or set an error in the context otherwise. */ * or set an error in the context otherwise. */
int redisGetReplyFromReader(redisContext *c, void **reply) { int redisGetReplyFromReader(redisContext *c, void **reply) {
if (redisReplyReaderGetReply(c->reader,reply) == REDIS_ERR) { if (redisReplyReaderGetReply(c->reader,reply) == REDIS_ERR) {
__redisSetError(c,REDIS_ERR_PROTOCOL, __redisSetError(c,REDIS_ERR_PROTOCOL,c->reader->errstr);
sdsnew(((redisReader*)c->reader)->errstr));
return REDIS_ERR; return REDIS_ERR;
} }
return REDIS_OK; return REDIS_OK;
......
...@@ -153,7 +153,7 @@ int redisFormatCommandArgv(char **target, int argc, const char **argv, const siz ...@@ -153,7 +153,7 @@ int redisFormatCommandArgv(char **target, int argc, const char **argv, const siz
/* Context for a connection to Redis */ /* Context for a connection to Redis */
typedef struct redisContext { typedef struct redisContext {
int err; /* Error flags, 0 when there is no error */ int err; /* Error flags, 0 when there is no error */
char *errstr; /* String representation of error when applicable */ char errstr[128]; /* String representation of error when applicable */
int fd; int fd;
int flags; int flags;
char *obuf; /* Write buffer */ char *obuf; /* Write buffer */
......
...@@ -49,18 +49,28 @@ ...@@ -49,18 +49,28 @@
#include "net.h" #include "net.h"
#include "sds.h" #include "sds.h"
/* Forward declaration */ /* Defined in hiredis.c */
void __redisSetError(redisContext *c, int type, sds err); void __redisSetError(redisContext *c, int type, const char *str);
static void __redisSetErrorFromErrno(redisContext *c, int type, const char *prefix) {
char buf[128];
size_t len = 0;
if (prefix != NULL)
len = snprintf(buf,sizeof(buf),"%s: ",prefix);
strerror_r(errno,buf+len,sizeof(buf)-len);
__redisSetError(c,type,buf);
}
static int redisCreateSocket(redisContext *c, int type) { static int redisCreateSocket(redisContext *c, int type) {
int s, on = 1; int s, on = 1;
if ((s = socket(type, SOCK_STREAM, 0)) == -1) { if ((s = socket(type, SOCK_STREAM, 0)) == -1) {
__redisSetError(c,REDIS_ERR_IO,NULL); __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
return REDIS_ERR; return REDIS_ERR;
} }
if (type == AF_INET) { if (type == AF_INET) {
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
__redisSetError(c,REDIS_ERR_IO,NULL); __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
close(s); close(s);
return REDIS_ERR; return REDIS_ERR;
} }
...@@ -75,8 +85,7 @@ static int redisSetBlocking(redisContext *c, int fd, int blocking) { ...@@ -75,8 +85,7 @@ static int redisSetBlocking(redisContext *c, int fd, int blocking) {
* Note that fcntl(2) for F_GETFL and F_SETFL can't be * Note that fcntl(2) for F_GETFL and F_SETFL can't be
* interrupted by a signal. */ * interrupted by a signal. */
if ((flags = fcntl(fd, F_GETFL)) == -1) { if ((flags = fcntl(fd, F_GETFL)) == -1) {
__redisSetError(c,REDIS_ERR_IO, __redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_GETFL)");
sdscatprintf(sdsempty(), "fcntl(F_GETFL): %s", strerror(errno)));
close(fd); close(fd);
return REDIS_ERR; return REDIS_ERR;
} }
...@@ -87,8 +96,7 @@ static int redisSetBlocking(redisContext *c, int fd, int blocking) { ...@@ -87,8 +96,7 @@ static int redisSetBlocking(redisContext *c, int fd, int blocking) {
flags |= O_NONBLOCK; flags |= O_NONBLOCK;
if (fcntl(fd, F_SETFL, flags) == -1) { if (fcntl(fd, F_SETFL, flags) == -1) {
__redisSetError(c,REDIS_ERR_IO, __redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_SETFL)");
sdscatprintf(sdsempty(), "fcntl(F_SETFL): %s", strerror(errno)));
close(fd); close(fd);
return REDIS_ERR; return REDIS_ERR;
} }
...@@ -98,8 +106,7 @@ static int redisSetBlocking(redisContext *c, int fd, int blocking) { ...@@ -98,8 +106,7 @@ static int redisSetBlocking(redisContext *c, int fd, int blocking) {
static int redisSetTcpNoDelay(redisContext *c, int fd) { static int redisSetTcpNoDelay(redisContext *c, int fd) {
int yes = 1; int yes = 1;
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1) { if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1) {
__redisSetError(c,REDIS_ERR_IO, __redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(TCP_NODELAY)");
sdscatprintf(sdsempty(), "setsockopt(TCP_NODELAY): %s", strerror(errno)));
close(fd); close(fd);
return REDIS_ERR; return REDIS_ERR;
} }
...@@ -124,15 +131,14 @@ static int redisContextWaitReady(redisContext *c, int fd, const struct timeval * ...@@ -124,15 +131,14 @@ static int redisContextWaitReady(redisContext *c, int fd, const struct timeval *
FD_SET(fd, &wfd); FD_SET(fd, &wfd);
if (select(FD_SETSIZE, NULL, &wfd, NULL, toptr) == -1) { if (select(FD_SETSIZE, NULL, &wfd, NULL, toptr) == -1) {
__redisSetError(c,REDIS_ERR_IO, __redisSetErrorFromErrno(c,REDIS_ERR_IO,"select(2)");
sdscatprintf(sdsempty(), "select(2): %s", strerror(errno)));
close(fd); close(fd);
return REDIS_ERR; return REDIS_ERR;
} }
if (!FD_ISSET(fd, &wfd)) { if (!FD_ISSET(fd, &wfd)) {
errno = ETIMEDOUT; errno = ETIMEDOUT;
__redisSetError(c,REDIS_ERR_IO,NULL); __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
close(fd); close(fd);
return REDIS_ERR; return REDIS_ERR;
} }
...@@ -140,15 +146,14 @@ static int redisContextWaitReady(redisContext *c, int fd, const struct timeval * ...@@ -140,15 +146,14 @@ static int redisContextWaitReady(redisContext *c, int fd, const struct timeval *
err = 0; err = 0;
errlen = sizeof(err); errlen = sizeof(err);
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) { if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {
__redisSetError(c,REDIS_ERR_IO, __redisSetErrorFromErrno(c,REDIS_ERR_IO,"getsockopt(SO_ERROR)");
sdscatprintf(sdsempty(), "getsockopt(SO_ERROR): %s", strerror(errno)));
close(fd); close(fd);
return REDIS_ERR; return REDIS_ERR;
} }
if (err) { if (err) {
errno = err; errno = err;
__redisSetError(c,REDIS_ERR_IO,NULL); __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
close(fd); close(fd);
return REDIS_ERR; return REDIS_ERR;
} }
...@@ -156,20 +161,18 @@ static int redisContextWaitReady(redisContext *c, int fd, const struct timeval * ...@@ -156,20 +161,18 @@ static int redisContextWaitReady(redisContext *c, int fd, const struct timeval *
return REDIS_OK; return REDIS_OK;
} }
__redisSetError(c,REDIS_ERR_IO,NULL); __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
close(fd); close(fd);
return REDIS_ERR; return REDIS_ERR;
} }
int redisContextSetTimeout(redisContext *c, struct timeval tv) { int redisContextSetTimeout(redisContext *c, struct timeval tv) {
if (setsockopt(c->fd,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv)) == -1) { if (setsockopt(c->fd,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv)) == -1) {
__redisSetError(c,REDIS_ERR_IO, __redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(SO_RCVTIMEO)");
sdscatprintf(sdsempty(), "setsockopt(SO_RCVTIMEO): %s", strerror(errno)));
return REDIS_ERR; return REDIS_ERR;
} }
if (setsockopt(c->fd,SOL_SOCKET,SO_SNDTIMEO,&tv,sizeof(tv)) == -1) { if (setsockopt(c->fd,SOL_SOCKET,SO_SNDTIMEO,&tv,sizeof(tv)) == -1) {
__redisSetError(c,REDIS_ERR_IO, __redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(SO_SNDTIMEO)");
sdscatprintf(sdsempty(), "setsockopt(SO_SNDTIMEO): %s", strerror(errno)));
return REDIS_ERR; return REDIS_ERR;
} }
return REDIS_OK; return REDIS_OK;
...@@ -192,8 +195,9 @@ int redisContextConnectTcp(redisContext *c, const char *addr, int port, struct t ...@@ -192,8 +195,9 @@ int redisContextConnectTcp(redisContext *c, const char *addr, int port, struct t
he = gethostbyname(addr); he = gethostbyname(addr);
if (he == NULL) { if (he == NULL) {
__redisSetError(c,REDIS_ERR_OTHER, char buf[128];
sdscatprintf(sdsempty(),"Can't resolve: %s",addr)); snprintf(buf,sizeof(buf),"Can't resolve: %s", addr);
__redisSetError(c,REDIS_ERR_OTHER,buf);
close(s); close(s);
return REDIS_ERR; return REDIS_ERR;
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment