From e9c245c5437f3ca584755fda8576c15169b7e9f4 Mon Sep 17 00:00:00 2001 From: sunmingqi Date: Wed, 3 Nov 2021 22:21:18 +0800 Subject: [PATCH 1/9] add timeout support for libuv adapter --- adapters/libuv.h | 54 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/adapters/libuv.h b/adapters/libuv.h index c120b1b39..b6924fad3 100644 --- a/adapters/libuv.h +++ b/adapters/libuv.h @@ -9,6 +9,7 @@ typedef struct redisLibuvEvents { redisAsyncContext* context; uv_poll_t handle; + uv_timer_t timer; int events; } redisLibuvEvents; @@ -69,19 +70,55 @@ static void redisLibuvDelWrite(void *privdata) { } } +static void on_timer_close(uv_handle_t *handle) { + // a dummy value, make sure callback is sequenced + handle->data = (void *)0xDEADBEEF; +} -static void on_close(uv_handle_t* handle) { +static void on_handle_close(uv_handle_t *handle) { redisLibuvEvents* p = (redisLibuvEvents*)handle->data; - + // note that the close callbacks is called sequentially + // so on_timer_close is always called before on_handle_close + assert(p->timer.data == (void *)0xDEADBEEF); + // just make sure callback is sequenced hi_free(p); } +static void redisLibuvTimeout(uv_timer_t *timer) { + redisLibuvEvents *e = (redisLibuvEvents*)timer->data; + redisAsyncHandleTimeout(e->context); +} + +static void redisLibuvSetTimeout(void *privdata, struct timeval tv) { + redisLibuvEvents* p = (redisLibuvEvents*)privdata; + + uint64_t millsec = tv.tv_sec * 1000 + tv.tv_usec / 1000.0; + if (p->timer.type == UV_UNKNOWN_HANDLE) { + // timer is uninitialized + if (uv_timer_init(p->handle.loop, &p->timer) != 0) { + return; + } + p->timer.data = p; + } + // updates the timeout if the timer has already started + // or start the timer + uv_timer_start(&p->timer, redisLibuvTimeout, millsec, 0); +} static void redisLibuvCleanup(void *privdata) { redisLibuvEvents* p = (redisLibuvEvents*)privdata; p->context = NULL; // indicate that context might no longer exist - uv_close((uv_handle_t*)&p->handle, on_close); + if (p->timer.type != UV_UNKNOWN_HANDLE) { + // note that the close callbacks is called sequentially + // so `on_timer_close` is always called before `on_handle_close` + // `uv_close` will stop the timer internally + uv_close((uv_handle_t*)&p->timer, on_timer_close); + } else { + p->timer.data = (void*)0xDEADBEEF; + // a dummy value, make sure callback is sequenced + } + uv_close((uv_handle_t*)&p->handle, on_handle_close); } @@ -92,11 +129,12 @@ static int redisLibuvAttach(redisAsyncContext* ac, uv_loop_t* loop) { return REDIS_ERR; } - ac->ev.addRead = redisLibuvAddRead; - ac->ev.delRead = redisLibuvDelRead; - ac->ev.addWrite = redisLibuvAddWrite; - ac->ev.delWrite = redisLibuvDelWrite; - ac->ev.cleanup = redisLibuvCleanup; + ac->ev.addRead = redisLibuvAddRead; + ac->ev.delRead = redisLibuvDelRead; + ac->ev.addWrite = redisLibuvAddWrite; + ac->ev.delWrite = redisLibuvDelWrite; + ac->ev.cleanup = redisLibuvCleanup; + ac->ev.scheduleTimer = redisLibuvSetTimeout; redisLibuvEvents* p = (redisLibuvEvents*)hi_malloc(sizeof(*p)); if (p == NULL) From 9a35ee99f0a24563d11f20ae75d260ef79f2ffa5 Mon Sep 17 00:00:00 2001 From: sunmingqi Date: Thu, 18 Nov 2021 14:19:06 +0800 Subject: [PATCH 2/9] change to 4-space indentation --- adapters/libuv.h | 178 +++++++++++++++++++++++------------------------ 1 file changed, 89 insertions(+), 89 deletions(-) diff --git a/adapters/libuv.h b/adapters/libuv.h index b6924fad3..7d6df5eba 100644 --- a/adapters/libuv.h +++ b/adapters/libuv.h @@ -7,149 +7,149 @@ #include typedef struct redisLibuvEvents { - redisAsyncContext* context; - uv_poll_t handle; - uv_timer_t timer; - int events; + redisAsyncContext* context; + uv_poll_t handle; + uv_timer_t timer; + int events; } redisLibuvEvents; static void redisLibuvPoll(uv_poll_t* handle, int status, int events) { - redisLibuvEvents* p = (redisLibuvEvents*)handle->data; - int ev = (status ? p->events : events); - - if (p->context != NULL && (ev & UV_READABLE)) { - redisAsyncHandleRead(p->context); - } - if (p->context != NULL && (ev & UV_WRITABLE)) { - redisAsyncHandleWrite(p->context); - } + redisLibuvEvents* p = (redisLibuvEvents*)handle->data; + int ev = (status ? p->events : events); + + if (p->context != NULL && (ev & UV_READABLE)) { + redisAsyncHandleRead(p->context); + } + if (p->context != NULL && (ev & UV_WRITABLE)) { + redisAsyncHandleWrite(p->context); + } } static void redisLibuvAddRead(void *privdata) { - redisLibuvEvents* p = (redisLibuvEvents*)privdata; + redisLibuvEvents* p = (redisLibuvEvents*)privdata; - p->events |= UV_READABLE; + p->events |= UV_READABLE; - uv_poll_start(&p->handle, p->events, redisLibuvPoll); + uv_poll_start(&p->handle, p->events, redisLibuvPoll); } static void redisLibuvDelRead(void *privdata) { - redisLibuvEvents* p = (redisLibuvEvents*)privdata; + redisLibuvEvents* p = (redisLibuvEvents*)privdata; - p->events &= ~UV_READABLE; + p->events &= ~UV_READABLE; - if (p->events) { - uv_poll_start(&p->handle, p->events, redisLibuvPoll); - } else { - uv_poll_stop(&p->handle); - } + 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; + redisLibuvEvents* p = (redisLibuvEvents*)privdata; - p->events |= UV_WRITABLE; + p->events |= UV_WRITABLE; - uv_poll_start(&p->handle, p->events, redisLibuvPoll); + uv_poll_start(&p->handle, p->events, redisLibuvPoll); } static void redisLibuvDelWrite(void *privdata) { - redisLibuvEvents* p = (redisLibuvEvents*)privdata; + redisLibuvEvents* p = (redisLibuvEvents*)privdata; - p->events &= ~UV_WRITABLE; + p->events &= ~UV_WRITABLE; - if (p->events) { - uv_poll_start(&p->handle, p->events, redisLibuvPoll); - } else { - uv_poll_stop(&p->handle); - } + if (p->events) { + uv_poll_start(&p->handle, p->events, redisLibuvPoll); + } else { + uv_poll_stop(&p->handle); + } } static void on_timer_close(uv_handle_t *handle) { - // a dummy value, make sure callback is sequenced - handle->data = (void *)0xDEADBEEF; + // a dummy value, make sure callback is sequenced + handle->data = (void *)0xDEADBEEF; } static void on_handle_close(uv_handle_t *handle) { - redisLibuvEvents* p = (redisLibuvEvents*)handle->data; - // note that the close callbacks is called sequentially - // so on_timer_close is always called before on_handle_close - assert(p->timer.data == (void *)0xDEADBEEF); - // just make sure callback is sequenced - hi_free(p); + redisLibuvEvents* p = (redisLibuvEvents*)handle->data; + // note that the close callbacks is called sequentially + // so on_timer_close is always called before on_handle_close + assert(p->timer.data == (void *)0xDEADBEEF); + // just make sure callback is sequenced + hi_free(p); } static void redisLibuvTimeout(uv_timer_t *timer) { - redisLibuvEvents *e = (redisLibuvEvents*)timer->data; - redisAsyncHandleTimeout(e->context); + redisLibuvEvents *e = (redisLibuvEvents*)timer->data; + redisAsyncHandleTimeout(e->context); } static void redisLibuvSetTimeout(void *privdata, struct timeval tv) { - redisLibuvEvents* p = (redisLibuvEvents*)privdata; - - uint64_t millsec = tv.tv_sec * 1000 + tv.tv_usec / 1000.0; - if (p->timer.type == UV_UNKNOWN_HANDLE) { - // timer is uninitialized - if (uv_timer_init(p->handle.loop, &p->timer) != 0) { - return; + redisLibuvEvents* p = (redisLibuvEvents*)privdata; + + uint64_t millsec = tv.tv_sec * 1000 + tv.tv_usec / 1000.0; + if (p->timer.type == UV_UNKNOWN_HANDLE) { + // timer is uninitialized + if (uv_timer_init(p->handle.loop, &p->timer) != 0) { + return; + } + p->timer.data = p; } - p->timer.data = p; - } - // updates the timeout if the timer has already started - // or start the timer - uv_timer_start(&p->timer, redisLibuvTimeout, millsec, 0); + // updates the timeout if the timer has already started + // or start the timer + uv_timer_start(&p->timer, redisLibuvTimeout, millsec, 0); } static void redisLibuvCleanup(void *privdata) { - redisLibuvEvents* p = (redisLibuvEvents*)privdata; - - p->context = NULL; // indicate that context might no longer exist - if (p->timer.type != UV_UNKNOWN_HANDLE) { - // note that the close callbacks is called sequentially - // so `on_timer_close` is always called before `on_handle_close` - // `uv_close` will stop the timer internally - uv_close((uv_handle_t*)&p->timer, on_timer_close); - } else { - p->timer.data = (void*)0xDEADBEEF; - // a dummy value, make sure callback is sequenced - } - uv_close((uv_handle_t*)&p->handle, on_handle_close); + redisLibuvEvents* p = (redisLibuvEvents*)privdata; + + p->context = NULL; // indicate that context might no longer exist + if (p->timer.type != UV_UNKNOWN_HANDLE) { + // note that the close callbacks is called sequentially + // so `on_timer_close` is always called before `on_handle_close` + // `uv_close` will stop the timer internally + uv_close((uv_handle_t*)&p->timer, on_timer_close); + } else { + p->timer.data = (void*)0xDEADBEEF; + // a dummy value, make sure callback is sequenced + } + uv_close((uv_handle_t*)&p->handle, on_handle_close); } static int redisLibuvAttach(redisAsyncContext* ac, uv_loop_t* loop) { - redisContext *c = &(ac->c); + redisContext *c = &(ac->c); - if (ac->ev.data != NULL) { - return REDIS_ERR; - } + 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; - ac->ev.scheduleTimer = redisLibuvSetTimeout; + ac->ev.addRead = redisLibuvAddRead; + ac->ev.delRead = redisLibuvDelRead; + ac->ev.addWrite = redisLibuvAddWrite; + ac->ev.delWrite = redisLibuvDelWrite; + ac->ev.cleanup = redisLibuvCleanup; + ac->ev.scheduleTimer = redisLibuvSetTimeout; - redisLibuvEvents* p = (redisLibuvEvents*)hi_malloc(sizeof(*p)); - if (p == NULL) - return REDIS_ERR; + redisLibuvEvents* p = (redisLibuvEvents*)hi_malloc(sizeof(*p)); + if (p == NULL) + return REDIS_ERR; - memset(p, 0, sizeof(*p)); + memset(p, 0, sizeof(*p)); - if (uv_poll_init_socket(loop, &p->handle, c->fd) != 0) { - return REDIS_ERR; - } + if (uv_poll_init_socket(loop, &p->handle, c->fd) != 0) { + return REDIS_ERR; + } - ac->ev.data = p; - p->handle.data = p; - p->context = ac; + ac->ev.data = p; + p->handle.data = p; + p->context = ac; - return REDIS_OK; + return REDIS_OK; } #endif From 1039d93c840fbb8bb4e0e429719385b154446d77 Mon Sep 17 00:00:00 2001 From: sunmingqi Date: Sun, 26 Dec 2021 14:53:20 +0800 Subject: [PATCH 3/9] fix asserion error in libuv timer support & add example --- Makefile | 2 ++ adapters/libuv.h | 30 ++++++++++++++--------------- examples/example-uvtm.c | 42 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 15 deletions(-) create mode 100644 examples/example-uvtm.c diff --git a/Makefile b/Makefile index 34c790989..d6e499621 100644 --- a/Makefile +++ b/Makefile @@ -166,6 +166,8 @@ hiredis-example-macosx: examples/example-macosx.c adapters/macosx.h $(STLIBNAME) hiredis-example-ssl: examples/example-ssl.c $(STLIBNAME) $(SSL_STLIBNAME) $(CC) -o examples/$@ $(REAL_CFLAGS) -I. $< $(STLIBNAME) $(SSL_STLIBNAME) $(REAL_LDFLAGS) $(SSL_LDFLAGS) +hiredis-example-uvtm: examples/example-uvtm.c adapters/libuv.h $(STLIBNAME) $(SSL_STLIBNAME) + $(CC) -o examples/$@ $(REAL_CFLAGS) -I. $< -luv $(STLIBNAME) $(SSL_STLIBNAME) $(REAL_LDFLAGS) $(SSL_LDFLAGS) ifndef AE_DIR hiredis-example-ae: diff --git a/adapters/libuv.h b/adapters/libuv.h index 7d6df5eba..6537f3da6 100644 --- a/adapters/libuv.h +++ b/adapters/libuv.h @@ -71,17 +71,23 @@ static void redisLibuvDelWrite(void *privdata) { } static void on_timer_close(uv_handle_t *handle) { - // a dummy value, make sure callback is sequenced - handle->data = (void *)0xDEADBEEF; + redisLibuvEvents* p = (redisLibuvEvents*)handle->data; + p->timer.data = NULL; + if (!p->handle.data) { + // both timer and handle are closed + hi_free(p); + } + // else, wait for `on_handle_close` } static void on_handle_close(uv_handle_t *handle) { redisLibuvEvents* p = (redisLibuvEvents*)handle->data; - // note that the close callbacks is called sequentially - // so on_timer_close is always called before on_handle_close - assert(p->timer.data == (void *)0xDEADBEEF); - // just make sure callback is sequenced - hi_free(p); + p->handle.data = NULL; + if (!p->timer.data) { + // timer never started, or timer already destroyed + hi_free(p); + } + // else, wait for `on_timer_close` } static void redisLibuvTimeout(uv_timer_t *timer) { @@ -93,7 +99,7 @@ static void redisLibuvSetTimeout(void *privdata, struct timeval tv) { redisLibuvEvents* p = (redisLibuvEvents*)privdata; uint64_t millsec = tv.tv_sec * 1000 + tv.tv_usec / 1000.0; - if (p->timer.type == UV_UNKNOWN_HANDLE) { + if (!p->timer.data) { // timer is uninitialized if (uv_timer_init(p->handle.loop, &p->timer) != 0) { return; @@ -109,14 +115,8 @@ static void redisLibuvCleanup(void *privdata) { redisLibuvEvents* p = (redisLibuvEvents*)privdata; p->context = NULL; // indicate that context might no longer exist - if (p->timer.type != UV_UNKNOWN_HANDLE) { - // note that the close callbacks is called sequentially - // so `on_timer_close` is always called before `on_handle_close` - // `uv_close` will stop the timer internally + if (p->timer.data) { uv_close((uv_handle_t*)&p->timer, on_timer_close); - } else { - p->timer.data = (void*)0xDEADBEEF; - // a dummy value, make sure callback is sequenced } uv_close((uv_handle_t*)&p->handle, on_handle_close); } diff --git a/examples/example-uvtm.c b/examples/example-uvtm.c new file mode 100644 index 000000000..59c21233f --- /dev/null +++ b/examples/example-uvtm.c @@ -0,0 +1,42 @@ + +// A libuv timeout example +// by github dot com slash michael-grunder +// many thanks! + +// usage: make hiredis-example-uvtm && ./examples/hiredis-example-uvtm + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +void sleepCb(redisAsyncContext *c, void *r, void *privdata) { + printf("sleep CB\n"); +} + +int main (int argc, char **argv) { +#ifndef _WIN32 + signal(SIGPIPE, SIG_IGN); +#endif + + 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); + redisAsyncSetTimeout(c, (struct timeval){ .tv_sec = 1, .tv_usec = 0}); + redisAsyncCommand(c, sleepCb, NULL, "DEBUG SLEEP %f", 1.5); + uv_run(loop, UV_RUN_DEFAULT); + return 0; +} From 351c1cfdb1d028bcbf01eb32ba6378bad8f3248c Mon Sep 17 00:00:00 2001 From: sunmingqi Date: Sat, 8 Jan 2022 00:42:45 +0800 Subject: [PATCH 4/9] merge `example-uvtm` with `example-libuv`, add more comments, fix compiler warnings --- Makefile | 10 ++++------ adapters/libuv.h | 7 ++++++- examples/example-libuv.c | 37 +++++++++++++++++++++++++++++------ examples/example-uvtm.c | 42 ---------------------------------------- 4 files changed, 41 insertions(+), 55 deletions(-) delete mode 100644 examples/example-uvtm.c diff --git a/Makefile b/Makefile index d6e499621..c134b9f98 100644 --- a/Makefile +++ b/Makefile @@ -166,9 +166,6 @@ hiredis-example-macosx: examples/example-macosx.c adapters/macosx.h $(STLIBNAME) hiredis-example-ssl: examples/example-ssl.c $(STLIBNAME) $(SSL_STLIBNAME) $(CC) -o examples/$@ $(REAL_CFLAGS) -I. $< $(STLIBNAME) $(SSL_STLIBNAME) $(REAL_LDFLAGS) $(SSL_LDFLAGS) -hiredis-example-uvtm: examples/example-uvtm.c adapters/libuv.h $(STLIBNAME) $(SSL_STLIBNAME) - $(CC) -o examples/$@ $(REAL_CFLAGS) -I. $< -luv $(STLIBNAME) $(SSL_STLIBNAME) $(REAL_LDFLAGS) $(SSL_LDFLAGS) - ifndef AE_DIR hiredis-example-ae: @echo "Please specify AE_DIR (e.g. /src)" @@ -179,10 +176,11 @@ hiredis-example-ae: examples/example-ae.c adapters/ae.h $(STLIBNAME) endif ifndef LIBUV_DIR -hiredis-example-libuv: - @echo "Please specify LIBUV_DIR (e.g. ../libuv/)" - @false +# dynamic link libuv.so +hiredis-example-libuv: examples/example-libuv.c adapters/libuv.h $(STLIBNAME) + $(CC) -o examples/$@ $(REAL_CFLAGS) -I. -I$(LIBUV_DIR)/include $< -luv -lpthread -lrt $(STLIBNAME) $(REAL_LDFLAGS) else +# use user provided static lib hiredis-example-libuv: examples/example-libuv.c adapters/libuv.h $(STLIBNAME) $(CC) -o examples/$@ $(REAL_CFLAGS) -I. -I$(LIBUV_DIR)/include $< $(LIBUV_DIR)/.libs/libuv.a -lpthread -lrt $(STLIBNAME) $(REAL_LDFLAGS) endif diff --git a/adapters/libuv.h b/adapters/libuv.h index 6537f3da6..7b6d955d1 100644 --- a/adapters/libuv.h +++ b/adapters/libuv.h @@ -108,7 +108,12 @@ static void redisLibuvSetTimeout(void *privdata, struct timeval tv) { } // updates the timeout if the timer has already started // or start the timer - uv_timer_start(&p->timer, redisLibuvTimeout, millsec, 0); + uv_timer_start(&p->timer, (uv_timer_cb)redisLibuvTimeout, millsec, 0); + // In some version of libuv, the `uv_timer_cb` have signature of + // `void(*)(uv_timer_t*, int), while in other version the signature is + // `void(*)(uv_timer_t*). Now that we don't care the second parameter, + // we simply convert the `redisLibuvTimeout` to (uv_timer_cb) to supress + // compiler warnings. } static void redisLibuvCleanup(void *privdata) { diff --git a/examples/example-libuv.c b/examples/example-libuv.c index cbde452b9..53fd04a8e 100644 --- a/examples/example-libuv.c +++ b/examples/example-libuv.c @@ -7,18 +7,33 @@ #include #include +void debugCallback(redisAsyncContext *c, void *r, void *privdata) { + (void)privdata; //unused + redisReply *reply = r; + if (reply == NULL) { + /* The DEBUG SLEEP command will almost always fail, because we have set a 1 second timeout */ + printf("`DEBUG SLEEP` error: %s\n", c->errstr ? c->errstr : "unknown error"); + return; + } + /* Disconnect after receiving the reply of DEBUG SLEEP (which will not)*/ + redisAsyncDisconnect(c); +} + void getCallback(redisAsyncContext *c, void *r, void *privdata) { redisReply *reply = r; - if (reply == NULL) return; - printf("argv[%s]: %s\n", (char*)privdata, reply->str); + if (reply == NULL) { + printf("`GET key` error: %s\n", c->errstr ? c->errstr : "unknown error"); + return; + } + printf("`GET key` result: argv[%s]: %s\n", (char*)privdata, reply->str); - /* Disconnect after receiving the reply to GET */ - redisAsyncDisconnect(c); + /* start another request that demonstrate timeout */ + redisAsyncCommand(c, debugCallback, NULL, "DEBUG SLEEP %f", 1.5); } void connectCallback(const redisAsyncContext *c, int status) { if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); + printf("connect error: %s\n", c->errstr); return; } printf("Connected...\n"); @@ -26,7 +41,7 @@ void connectCallback(const redisAsyncContext *c, int status) { void disconnectCallback(const redisAsyncContext *c, int status) { if (status != REDIS_OK) { - printf("Error: %s\n", c->errstr); + printf("disconnect because of error: %s\n", c->errstr); return; } printf("Disconnected...\n"); @@ -49,8 +64,18 @@ int main (int argc, char **argv) { redisLibuvAttach(c,loop); redisAsyncSetConnectCallback(c,connectCallback); redisAsyncSetDisconnectCallback(c,disconnectCallback); + redisAsyncSetTimeout(c, (struct timeval){ .tv_sec = 1, .tv_usec = 0}); + + /* + In this demo, we first `set key`, then `get key` to demonstrate the basic usage of libuv adapter. + Then in `getCallback`, we start a `debug sleep` command to create 1.5 second long request. + Because we have set a 1 second timeout to the connection, the command will always fail with a + timeout error, which is shown in the `debugCallback`. + */ + 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/examples/example-uvtm.c b/examples/example-uvtm.c deleted file mode 100644 index 59c21233f..000000000 --- a/examples/example-uvtm.c +++ /dev/null @@ -1,42 +0,0 @@ - -// A libuv timeout example -// by github dot com slash michael-grunder -// many thanks! - -// usage: make hiredis-example-uvtm && ./examples/hiredis-example-uvtm - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -void sleepCb(redisAsyncContext *c, void *r, void *privdata) { - printf("sleep CB\n"); -} - -int main (int argc, char **argv) { -#ifndef _WIN32 - signal(SIGPIPE, SIG_IGN); -#endif - - 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); - redisAsyncSetTimeout(c, (struct timeval){ .tv_sec = 1, .tv_usec = 0}); - redisAsyncCommand(c, sleepCb, NULL, "DEBUG SLEEP %f", 1.5); - uv_run(loop, UV_RUN_DEFAULT); - return 0; -} From 6403e415778aa5b1ecd0fe40341c807d23d527ff Mon Sep 17 00:00:00 2001 From: sunmingqi Date: Sat, 8 Jan 2022 13:40:58 +0800 Subject: [PATCH 5/9] adapt libuv interface change on `uv_timer_cb` --- adapters/libuv.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/adapters/libuv.h b/adapters/libuv.h index 7b6d955d1..fed731693 100644 --- a/adapters/libuv.h +++ b/adapters/libuv.h @@ -90,7 +90,14 @@ static void on_handle_close(uv_handle_t *handle) { // else, wait for `on_timer_close` } +#if UV_MAJOR_VERSION > 0 || UV_MINOR_VERSION > 11 || (defined(UV_VERSION_PATCH) && UV_VERSION_PATCH > 22) +// libuv removed `status` parameter since v0.11.23 +// see: /~https://github.com/libuv/libuv/blob/v0.11.23/include/uv.h static void redisLibuvTimeout(uv_timer_t *timer) { +#else +static void redisLibuvTimeout(uv_timer_t *timer, int status) { + (void)status; // unused +#endif redisLibuvEvents *e = (redisLibuvEvents*)timer->data; redisAsyncHandleTimeout(e->context); } @@ -108,12 +115,7 @@ static void redisLibuvSetTimeout(void *privdata, struct timeval tv) { } // updates the timeout if the timer has already started // or start the timer - uv_timer_start(&p->timer, (uv_timer_cb)redisLibuvTimeout, millsec, 0); - // In some version of libuv, the `uv_timer_cb` have signature of - // `void(*)(uv_timer_t*, int), while in other version the signature is - // `void(*)(uv_timer_t*). Now that we don't care the second parameter, - // we simply convert the `redisLibuvTimeout` to (uv_timer_cb) to supress - // compiler warnings. + uv_timer_start(&p->timer, redisLibuvTimeout, millsec, 0); } static void redisLibuvCleanup(void *privdata) { From e6b4fb24ee8c61a7068ebd098b177e63493f6d29 Mon Sep 17 00:00:00 2001 From: MichaelSuen Date: Thu, 13 Jan 2022 22:30:35 +0800 Subject: [PATCH 6/9] change to a cleaner version check macro Co-authored-by: Michael Grunder --- adapters/libuv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adapters/libuv.h b/adapters/libuv.h index fed731693..92c0754ff 100644 --- a/adapters/libuv.h +++ b/adapters/libuv.h @@ -90,7 +90,7 @@ static void on_handle_close(uv_handle_t *handle) { // else, wait for `on_timer_close` } -#if UV_MAJOR_VERSION > 0 || UV_MINOR_VERSION > 11 || (defined(UV_VERSION_PATCH) && UV_VERSION_PATCH > 22) +#if !defined(UV_VERSION_PATCH) || (UV_MAJOR_VERSION < 1 && UV_MINOR_VERSION < 12 && UV_VERSION_PATCH < 23) // libuv removed `status` parameter since v0.11.23 // see: /~https://github.com/libuv/libuv/blob/v0.11.23/include/uv.h static void redisLibuvTimeout(uv_timer_t *timer) { From 44903ed17abf404f70d3bc2aec806793cb34c9ef Mon Sep 17 00:00:00 2001 From: sunmingqi Date: Fri, 14 Jan 2022 00:12:26 +0800 Subject: [PATCH 7/9] correct version check macro, fix a silly typo --- adapters/libuv.h | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/adapters/libuv.h b/adapters/libuv.h index 92c0754ff..614272365 100644 --- a/adapters/libuv.h +++ b/adapters/libuv.h @@ -90,13 +90,21 @@ static void on_handle_close(uv_handle_t *handle) { // else, wait for `on_timer_close` } -#if !defined(UV_VERSION_PATCH) || (UV_MAJOR_VERSION < 1 && UV_MINOR_VERSION < 12 && UV_VERSION_PATCH < 23) // libuv removed `status` parameter since v0.11.23 // see: /~https://github.com/libuv/libuv/blob/v0.11.23/include/uv.h -static void redisLibuvTimeout(uv_timer_t *timer) { -#else +// explain: +// 1. !defined(UV_VERSION_PATCH), must < 0.10.2 +// 2. major.minor.patch < 0.11.23 +// => (major < 0) || (major == 0 && minor < 11) || (minor == 11 && patch < 23) +// major < 0 can't happen +// => (major == 0 && minor < 11) || (minor == 11 && patch < 23) + +// < 0.10.2 goes here < 0.10.2~x goes here 0.11.0~22 goes here +#if !defined(UV_VERSION_PATCH) || (UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR < 11) || (UV_VERSION_MINOR == 11 && UV_VERSION_PATCH < 23) static void redisLibuvTimeout(uv_timer_t *timer, int status) { (void)status; // unused +#else +static void redisLibuvTimeout(uv_timer_t *timer) { #endif redisLibuvEvents *e = (redisLibuvEvents*)timer->data; redisAsyncHandleTimeout(e->context); From 47a1ec7fd80502c4caadcf592daf008d05b8bcd0 Mon Sep 17 00:00:00 2001 From: MichaelSuen Date: Fri, 14 Jan 2022 00:51:05 +0800 Subject: [PATCH 8/9] Accept suggested version check macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Viktor Söderqvist --- adapters/libuv.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/adapters/libuv.h b/adapters/libuv.h index 614272365..afab4d106 100644 --- a/adapters/libuv.h +++ b/adapters/libuv.h @@ -100,7 +100,8 @@ static void on_handle_close(uv_handle_t *handle) { // => (major == 0 && minor < 11) || (minor == 11 && patch < 23) // < 0.10.2 goes here < 0.10.2~x goes here 0.11.0~22 goes here -#if !defined(UV_VERSION_PATCH) || (UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR < 11) || (UV_VERSION_MINOR == 11 && UV_VERSION_PATCH < 23) +#if (UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR < 11) || \ + (UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR == 11 && UV_VERSION_PATCH < 23) static void redisLibuvTimeout(uv_timer_t *timer, int status) { (void)status; // unused #else From 1539b7d0b7a0a152b4465a96d41df19ea8ba1b6f Mon Sep 17 00:00:00 2001 From: sunmingqi Date: Fri, 14 Jan 2022 13:58:19 +0800 Subject: [PATCH 9/9] remove outdated comments --- adapters/libuv.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/adapters/libuv.h b/adapters/libuv.h index afab4d106..df0a84578 100644 --- a/adapters/libuv.h +++ b/adapters/libuv.h @@ -92,14 +92,6 @@ static void on_handle_close(uv_handle_t *handle) { // libuv removed `status` parameter since v0.11.23 // see: /~https://github.com/libuv/libuv/blob/v0.11.23/include/uv.h -// explain: -// 1. !defined(UV_VERSION_PATCH), must < 0.10.2 -// 2. major.minor.patch < 0.11.23 -// => (major < 0) || (major == 0 && minor < 11) || (minor == 11 && patch < 23) -// major < 0 can't happen -// => (major == 0 && minor < 11) || (minor == 11 && patch < 23) - -// < 0.10.2 goes here < 0.10.2~x goes here 0.11.0~22 goes here #if (UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR < 11) || \ (UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR == 11 && UV_VERSION_PATCH < 23) static void redisLibuvTimeout(uv_timer_t *timer, int status) {