summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2017-07-11 00:13:52 +0200
committerantirez <antirez@gmail.com>2017-07-11 00:13:52 +0200
commit54e4bbeabdd1cd92e5c2b461f85c6c03d8645838 (patch)
tree9cd9d8021aeab6dd2cd7242d08cc3b8bf84549a0
parent11182a1a58ef6d36f76f7a5e06d0598254b524d9 (diff)
downloadredis-54e4bbeabdd1cd92e5c2b461f85c6c03d8645838.tar.gz
Event loop: call after sleep() only from top level.
In general we do not want before/after sleep() callbacks to be called when we re-enter the event loop, since those calls are only designed in order to perform operations every main iteration of the event loop, and re-entering is often just a way to incrementally serve clietns with error messages or other auxiliary operations. However, if we call the callbacks, we are then forced to think at before/after sleep callbacks as re-entrant, which is much harder without any good need. However here there was also a clear bug: beforeSleep() was actually never called when re-entering the event loop. But the new afterSleep() callback was. This is broken and in this instance re-entering afterSleep() caused a modules GIL dead lock.
-rw-r--r--src/ae.c5
-rw-r--r--src/ae.h1
2 files changed, 4 insertions, 2 deletions
diff --git a/src/ae.c b/src/ae.c
index ecbaa94f3..742388d85 100644
--- a/src/ae.c
+++ b/src/ae.c
@@ -344,6 +344,7 @@ static int processTimeEvents(aeEventLoop *eventLoop) {
* if flags has AE_FILE_EVENTS set, file events are processed.
* if flags has AE_TIME_EVENTS set, time events are processed.
* if flags has AE_DONT_WAIT set the function returns ASAP until all
+ * if flags has AE_CALL_AFTER_SLEEP set, the aftersleep callback is called.
* the events that's possible to process without to wait are processed.
*
* The function returns the number of events processed. */
@@ -403,7 +404,7 @@ int aeProcessEvents(aeEventLoop *eventLoop, int flags)
numevents = aeApiPoll(eventLoop, tvp);
/* After sleep callback. */
- if (eventLoop->aftersleep != NULL)
+ if (eventLoop->aftersleep != NULL && flags & AE_CALL_AFTER_SLEEP)
eventLoop->aftersleep(eventLoop);
for (j = 0; j < numevents; j++) {
@@ -460,7 +461,7 @@ void aeMain(aeEventLoop *eventLoop) {
while (!eventLoop->stop) {
if (eventLoop->beforesleep != NULL)
eventLoop->beforesleep(eventLoop);
- aeProcessEvents(eventLoop, AE_ALL_EVENTS);
+ aeProcessEvents(eventLoop, AE_ALL_EVENTS|AE_CALL_AFTER_SLEEP);
}
}
diff --git a/src/ae.h b/src/ae.h
index e3617759b..c49bfe233 100644
--- a/src/ae.h
+++ b/src/ae.h
@@ -46,6 +46,7 @@
#define AE_TIME_EVENTS 2
#define AE_ALL_EVENTS (AE_FILE_EVENTS|AE_TIME_EVENTS)
#define AE_DONT_WAIT 4
+#define AE_CALL_AFTER_SLEEP 8
#define AE_NOMORE -1
#define AE_DELETED_EVENT_ID -1