From 65470cb48fabbf46f4acfd23652bcc47d0d47acd Mon Sep 17 00:00:00 2001
From: Ilya Verbin <iverbin@tarantool.org>
Date: Fri, 10 Jun 2022 20:21:48 +0300
Subject: [PATCH] core: get rid of fiber_set_cancellable in hot_standby_f

Currently it's possible to wakeup a `hot_standby_f` fiber from Lua,
this does not lead to any error, but it results in redundant
`recover_remaining_wals` calls.
This patch handles such spurious wakeups in `hot_standby_f`.

Part of #7166

NO_DOC=refactoring
NO_TEST=refactoring
NO_CHANGELOG=refactoring
---
 src/box/recovery.cc | 18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/src/box/recovery.cc b/src/box/recovery.cc
index cbefded052..331164ced5 100644
--- a/src/box/recovery.cc
+++ b/src/box/recovery.cc
@@ -403,8 +403,7 @@ class WalSubscription {
 	void wakeup(unsigned events)
 	{
 		this->events |= events;
-		if (f->flags & FIBER_IS_CANCELLABLE)
-			fiber_wakeup(f);
+		fiber_wakeup(f);
 	}
 
 	WalSubscription(const char *wal_dir)
@@ -500,14 +499,12 @@ hot_standby_f(va_list ap)
 					  r->cursor.name : NULL);
 
 		bool timed_out = false;
-		if (subscription.events == 0) {
-			/**
-			 * Allow an immediate wakeup/break loop
-			 * from recovery_stop_local().
-			 */
-			fiber_set_cancellable(true);
-			timed_out = fiber_yield_timeout(wal_dir_rescan_delay);
-			fiber_set_cancellable(false);
+		ev_tstamp deadline = ev_monotonic_now(loop())
+				     + wal_dir_rescan_delay;
+		while (r->watcher != NULL &&
+		       !timed_out &&
+		       subscription.events == 0) {
+			timed_out = fiber_yield_deadline(deadline);
 		}
 
 		scan_dir = timed_out ||
@@ -538,6 +535,7 @@ recovery_stop_local(struct recovery *r)
 {
 	if (r->watcher) {
 		struct fiber *f = r->watcher;
+		/* Break the loop in hot_standby_f(). */
 		r->watcher = NULL;
 		fiber_cancel(f);
 		if (fiber_join(f) != 0)
-- 
GitLab