diff options
author | Oran Agra <oran@redislabs.com> | 2020-11-22 14:00:51 +0200 |
---|---|---|
committer | Oran Agra <oran@redislabs.com> | 2021-01-12 16:25:37 +0200 |
commit | f885e364ba9b9fe83b9b94e665547d70040ee89c (patch) | |
tree | 657ff29a0b1f07ca849cbec8721ad478b22f4c02 | |
parent | 3ac666b3e6f9fad55ba9da6a60cb5aaf78dda156 (diff) | |
download | redis-f885e364ba9b9fe83b9b94e665547d70040ee89c.tar.gz |
Fix bug with module GIL being released prematurely (#8061)
This is hopefully usually harmles.
The server.ready_keys will usually be empty so the code after releasing
the GIL will soon be done.
The only case where it'll actually process things is when a module
releases a client (or module) blocked on a key, by triggering this NOT
from within a command (e.g. a timer event).
This bug was introduced in redis 6.0.9, see #7903
(cherry picked from commit e6fa47380a5274119ed37c7a5ea7455d4b7dbdcc)
-rw-r--r-- | src/server.c | 13 |
1 files changed, 9 insertions, 4 deletions
diff --git a/src/server.c b/src/server.c index 09652294d..1f29c1d93 100644 --- a/src/server.c +++ b/src/server.c @@ -2199,15 +2199,17 @@ void beforeSleep(struct aeEventLoop *eventLoop) { /* Close clients that need to be closed asynchronous */ freeClientsInAsyncFreeQueue(); + /* Try to process blocked clients every once in while. Example: A module + * calls RM_SignalKeyAsReady from within a timer callback (So we don't + * visit processCommand() at all). */ + handleClientsBlockedOnKeys(); + /* Before we are going to sleep, let the threads access the dataset by * releasing the GIL. Redis main thread will not touch anything at this * time. */ if (moduleCount()) moduleReleaseGIL(); - /* Try to process blocked clients every once in while. Example: A module - * calls RM_SignalKeyAsReady from within a timer callback (So we don't - * visit processCommand() at all). */ - handleClientsBlockedOnKeys(); + /* Do NOT add anything below moduleReleaseGIL !!! */ } /* This function is called immediately after the event loop multiplexing @@ -2216,6 +2218,9 @@ void beforeSleep(struct aeEventLoop *eventLoop) { void afterSleep(struct aeEventLoop *eventLoop) { UNUSED(eventLoop); + /* Do NOT add anything above moduleAcquireGIL !!! */ + + /* Aquire the modules GIL so that their threads won't touch anything. */ if (!ProcessingEventsWhileBlocked) { if (moduleCount()) moduleAcquireGIL(); } |