From ecd53518700f5b2be19c18e7a19f87c9f25a7ff5 Mon Sep 17 00:00:00 2001 From: "Meir Shpilraien (Spielrein)" Date: Mon, 4 Jan 2021 13:42:17 +0200 Subject: [PATCH] Fix assertion on loading AOF with timed out script. (#8284) If AOF file contains a long Lua script that timed out, then the `evalCommand` calls `blockingOperationEnds` which sets `server.blocked_last_cron` to 0. later on, the AOF `whileBlockedCron` function asserts that this value is not 0. The fix allows nesting call to `blockingOperationStarts` and `blockingOperationEnds`. The issue was first introduce in this commit: 9ef8d2f67 (Redis 6.2 RC1) --- src/server.c | 11 ++++++++--- src/server.h | 1 + 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/server.c b/src/server.c index 7ecfa8d1b..1fee70789 100644 --- a/src/server.c +++ b/src/server.c @@ -2187,12 +2187,16 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) { void blockingOperationStarts() { - updateCachedTime(0); - server.blocked_last_cron = server.mstime; + if(!server.blocking_op_nesting++){ + updateCachedTime(0); + server.blocked_last_cron = server.mstime; + } } void blockingOperationEnds() { - server.blocked_last_cron = 0; + if(!(--server.blocking_op_nesting)){ + server.blocked_last_cron = 0; + } } /* This function fill in the role of serverCron during RDB or AOF loading, and @@ -3004,6 +3008,7 @@ void initServer(void) { server.events_processed_while_blocked = 0; server.system_memory_size = zmalloc_get_memory_size(); server.blocked_last_cron = 0; + server.blocking_op_nesting = 0; if ((server.tls_port || server.tls_replication || server.tls_cluster) && tlsConfigure(&server.tls_ctx_config) == C_ERR) { diff --git a/src/server.h b/src/server.h index 5f6b21ec4..aaee5a35d 100644 --- a/src/server.h +++ b/src/server.h @@ -1468,6 +1468,7 @@ struct redisServer { int daylight_active; /* Currently in daylight saving time. */ mstime_t mstime; /* 'unixtime' in milliseconds. */ ustime_t ustime; /* 'unixtime' in microseconds. */ + size_t blocking_op_nesting; /* Nesting level of blocking operation, used to reset blocked_last_cron. */ long long blocked_last_cron; /* Indicate the mstime of the last time we did cron jobs from a blocking operation */ /* Pubsub */ dict *pubsub_channels; /* Map channels to list of subscribed clients */