Skip to content

Instantly share code, notes, and snippets.

@michael-grunder
Created December 22, 2021 20:39
Show Gist options
  • Save michael-grunder/fe23fd182cec38027118b82cf1ad4e56 to your computer and use it in GitHub Desktop.
Save michael-grunder/fe23fd182cec38027118b82cf1ad4e56 to your computer and use it in GitHub Desktop.
Add a timeout to the libuv hiredis adapter
diff --git a/adapters/libuv.h b/adapters/libuv.h
index c120b1b..b0b9ed4 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;
@@ -76,11 +77,32 @@ static void on_close(uv_handle_t* handle) {
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;
+ }
+ 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) {
+ uv_timer_stop(&p->timer);
+ }
uv_close((uv_handle_t*)&p->handle, on_close);
}
@@ -92,11 +114,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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment