From 5aa2397f9ec494380774fb9155446f14ebbf3d1f Mon Sep 17 00:00:00 2001 From: Mark Nunberg Date: Thu, 11 Apr 2019 15:08:27 -0400 Subject: [PATCH] fix blocking timeouts on SSL reads/writes --- sslio.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/sslio.c b/sslio.c index efbf06e..25cb5c2 100644 --- a/sslio.c +++ b/sslio.c @@ -4,6 +4,7 @@ #include #ifdef HIREDIS_SSL #include +#include void __redisSetError(redisContext *c, int type, const char *str); @@ -184,6 +185,28 @@ int redisSslRead(redisContext *c, char *buf, size_t bufcap) { return -1; } else { int err = SSL_get_error(c->ssl->ssl, nread); + if (c->flags & REDIS_BLOCK) { + /** + * In blocking mode, we should never end up in a situation where + * we get an error without it being an actual error, except + * in the case of EINTR, which can be spuriously received from + * debuggers or whatever. + */ + if (errno == EINTR) { + return 0; + } else { + const char *msg = NULL; + if (errno == EAGAIN) { + msg = "Timed out"; + } + __redisSetError(c, REDIS_ERR_IO, msg); + return -1; + } + } + + /** + * We can very well get an EWOULDBLOCK/EAGAIN, however + */ if (maybeCheckWant(c->ssl, err)) { return 0; } else { @@ -203,7 +226,7 @@ int redisSslWrite(redisContext *c) { c->ssl->lastLen = len; int err = SSL_get_error(c->ssl->ssl, rv); - if (maybeCheckWant(c->ssl, err)) { + if ((c->flags & REDIS_BLOCK) == 0 && maybeCheckWant(c->ssl, err)) { return 0; } else { __redisSetError(c, REDIS_ERR_IO, NULL);