From e2b59c13a3bffd12d642d1e10cf068c99f985b1c Mon Sep 17 00:00:00 2001 From: Yossi Gottlieb Date: Sun, 10 May 2020 17:38:04 +0300 Subject: [PATCH 1/4] TLS: Fix test failures on recent Debian/Ubuntu. Seems like on some systems choosing specific TLS v1/v1.1 versions no longer works as expected. Test is reduced for v1.2 now which is still good enough to test the mechansim, and matters most anyway. --- tests/unit/tls.tcl | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/tests/unit/tls.tcl b/tests/unit/tls.tcl index 950f65557..2b04590cd 100644 --- a/tests/unit/tls.tcl +++ b/tests/unit/tls.tcl @@ -25,26 +25,6 @@ start_server {tags {"tls"}} { } test {TLS: Verify tls-protocols behaves as expected} { - r CONFIG SET tls-protocols TLSv1 - - set s [redis [srv 0 host] [srv 0 port] 0 1 {-tls1 0}] - catch {$s PING} e - assert_match {*I/O error*} $e - - set s [redis [srv 0 host] [srv 0 port] 0 1 {-tls1 1}] - catch {$s PING} e - assert_match {PONG} $e - - r CONFIG SET tls-protocols TLSv1.1 - - set s [redis [srv 0 host] [srv 0 port] 0 1 {-tls1.1 0}] - catch {$s PING} e - assert_match {*I/O error*} $e - - set s [redis [srv 0 host] [srv 0 port] 0 1 {-tls1.1 1}] - catch {$s PING} e - assert_match {PONG} $e - r CONFIG SET tls-protocols TLSv1.2 set s [redis [srv 0 host] [srv 0 port] 0 1 {-tls1.2 0}] From e15f563368343bb92a014c6a9ccb2fc5dfab8843 Mon Sep 17 00:00:00 2001 From: Yossi Gottlieb Date: Sun, 10 May 2020 17:35:27 +0300 Subject: [PATCH 2/4] TLS: Add crypto locks for older OpenSSL support. This is really required only for older OpenSSL versions. Also, at the moment Redis does not use OpenSSL from multiple threads so this will only be useful if modules end up doing that. --- src/tls.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/tls.c b/src/tls.c index c18aafebe..cfd6ea234 100644 --- a/src/tls.c +++ b/src/tls.c @@ -93,11 +93,56 @@ static int parseProtocolsConfig(const char *str) { * served to the reader yet. */ static list *pending_list = NULL; +/** + * OpenSSL global initialization and locking handling callbacks. + * Note that this is only required for OpenSSL < 1.1.0. + */ + +#if OPENSSL_VERSION_NUMBER < 0x10100000L +#define USE_CRYPTO_LOCKS +#endif + +#ifdef USE_CRYPTO_LOCKS + +static pthread_mutex_t *openssl_locks; + +static void sslLockingCallback(int mode, int lock_id, const char *f, int line) { + pthread_mutex_t *mt = openssl_locks + lock_id; + + if (mode & CRYPTO_LOCK) { + pthread_mutex_lock(mt); + } else { + pthread_mutex_unlock(mt); + } + + (void)f; + (void)line; +} + +static void initCryptoLocks(void) { + unsigned i, nlocks; + if (CRYPTO_get_locking_callback() != NULL) { + /* Someone already set the callback before us. Don't destroy it! */ + return; + } + nlocks = CRYPTO_num_locks(); + openssl_locks = zmalloc(sizeof(*openssl_locks) * nlocks); + for (i = 0; i < nlocks; i++) { + pthread_mutex_init(openssl_locks + i, NULL); + } + CRYPTO_set_locking_callback(sslLockingCallback); +} +#endif /* USE_CRYPTO_LOCKS */ + void tlsInit(void) { ERR_load_crypto_strings(); SSL_load_error_strings(); SSL_library_init(); +#ifdef USE_CRYPTO_LOCKS + initCryptoLocks(); +#endif + if (!RAND_poll()) { serverLog(LL_WARNING, "OpenSSL: Failed to seed random number generator."); } From f75ab4fcb518d0550b48639722fea166fdd0e078 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Tue, 12 May 2020 21:19:12 +0100 Subject: [PATCH 3/4] NetBSD build update. This platform supports CPU affinity (but not OpenBSD). --- src/Makefile | 10 ++++++++++ src/config.h | 2 +- src/setcpuaffinity.c | 19 +++++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 55f862cfc..b8c05c32b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -128,6 +128,14 @@ else ifeq ($(uname_S),DragonFly) # FreeBSD FINAL_LIBS+= -lpthread -lexecinfo +else +ifeq ($(uname_S),OpenBSD) + # OpenBSD + FINAL_LIBS+= -lpthread -lexecinfo +else +ifeq ($(uname_S),NetBSD) + # NetBSD + FINAL_LIBS+= -lpthread -lexecinfo else # All the other OSes (notably Linux) FINAL_LDFLAGS+= -rdynamic @@ -138,6 +146,8 @@ endif endif endif endif +endif +endif # Include paths to dependencies FINAL_CFLAGS+= -I../deps/hiredis -I../deps/linenoise -I../deps/lua/src diff --git a/src/config.h b/src/config.h index 6025d4e96..0fcc42972 100644 --- a/src/config.h +++ b/src/config.h @@ -248,7 +248,7 @@ int pthread_setname_np(const char *name); #endif /* Check if we can use setcpuaffinity(). */ -#if (defined __linux || defined __NetBSD__ || defined __FreeBSD__ || defined __OpenBSD__) +#if (defined __linux || defined __NetBSD__ || defined __FreeBSD__) #define USE_SETCPUAFFINITY void setcpuaffinity(const char *cpulist); #endif diff --git a/src/setcpuaffinity.c b/src/setcpuaffinity.c index dcae81c71..13594113c 100644 --- a/src/setcpuaffinity.c +++ b/src/setcpuaffinity.c @@ -36,6 +36,10 @@ #include #include #endif +#ifdef __NetBSD__ +#include +#include +#endif #include "config.h" #ifdef USE_SETCPUAFFINITY @@ -71,11 +75,18 @@ void setcpuaffinity(const char *cpulist) { #ifdef __FreeBSD__ cpuset_t cpuset; #endif +#ifdef __NetBSD__ + cpuset_t *cpuset; +#endif if (!cpulist) return; +#ifndef __NetBSD__ CPU_ZERO(&cpuset); +#else + cpuset = cpuset_create(); +#endif q = cpulist; while (p = q, q = next_token(q, ','), p) { @@ -110,7 +121,11 @@ void setcpuaffinity(const char *cpulist) { return; while (a <= b) { +#ifndef __NetBSD__ CPU_SET(a, &cpuset); +#else + cpuset_set(a, cpuset); +#endif a += s; } } @@ -124,6 +139,10 @@ void setcpuaffinity(const char *cpulist) { #ifdef __FreeBSD__ cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, sizeof(cpuset), &cpuset); #endif +#ifdef __NetBSD__ + pthread_setaffinity_np(pthread_self(), cpuset_size(cpuset), cpuset); + cpuset_destroy(cpuset); +#endif } #endif /* USE_SETCPUAFFINITY */ From 1bc06c7e8577ccc9f634fba9bcc90648a8dec9f3 Mon Sep 17 00:00:00 2001 From: Madelyn Olson Date: Thu, 14 May 2020 08:37:24 -0700 Subject: [PATCH 4/4] Added a refcount on timer events to prevent deletion of recursive timer calls --- src/ae.c | 10 ++++++++++ src/ae.h | 2 ++ 2 files changed, 12 insertions(+) diff --git a/src/ae.c b/src/ae.c index 379cfd1e6..689a27d16 100644 --- a/src/ae.c +++ b/src/ae.c @@ -238,6 +238,7 @@ long long aeCreateTimeEvent(aeEventLoop *eventLoop, long long milliseconds, te->clientData = clientData; te->prev = NULL; te->next = eventLoop->timeEventHead; + te->refcount = 0; if (te->next) te->next->prev = te; eventLoop->timeEventHead = te; @@ -316,6 +317,13 @@ static int processTimeEvents(aeEventLoop *eventLoop) { /* Remove events scheduled for deletion. */ if (te->id == AE_DELETED_EVENT_ID) { aeTimeEvent *next = te->next; + /* If a reference exists for this timer event, + * don't free it. This is currently incremented + * for recursive timerProc calls */ + if (te->refcount) { + te = next; + continue; + } if (te->prev) te->prev->next = te->next; else @@ -345,7 +353,9 @@ static int processTimeEvents(aeEventLoop *eventLoop) { int retval; id = te->id; + te->refcount++; retval = te->timeProc(eventLoop, id, te->clientData); + te->refcount--; processed++; if (retval != AE_NOMORE) { aeAddMillisecondsToNow(retval,&te->when_sec,&te->when_ms); diff --git a/src/ae.h b/src/ae.h index 63b306615..d1b7f34bf 100644 --- a/src/ae.h +++ b/src/ae.h @@ -86,6 +86,8 @@ typedef struct aeTimeEvent { void *clientData; struct aeTimeEvent *prev; struct aeTimeEvent *next; + int refcount; /* refcount to prevent timer events from being + * freed in recursive time event calls. */ } aeTimeEvent; /* A fired event */