From 1bb3ee93adcb3fdeeaab554747b3fa7a06e98654 Mon Sep 17 00:00:00 2001
From: Andrey Saranchin <Andrey22102001@gmail.com>
Date: Wed, 24 Jul 2024 14:46:28 +0300
Subject: [PATCH] memtx: allow to abort checkpoint if it wasn't started

When checkpoint fails, we abort it in all engines even if it wasn't
started successfully. If it fails right from the start so that checkpoint
in memtx wasn't started, assertion in `memtx_engine_abort_checkpoint`
fails - memtx doesn't expect that checkpoint will be aborted if it
failed to start. Let's do the same thing as vinyl does - no-op if
there is no checkpoint in progress.

Closes #10265

NO_CHANGELOG=reproducible only with error injection
NO_DOC=bugfix

(cherry picked from commit 6b484622259c01a2468b1f248dd6f1bcdc227021)
---
 src/box/memtx_engine.cc                       |  2 ++
 ...5_memtx_checkpoint_fail_assertion_test.lua | 28 +++++++++++++++++++
 2 files changed, 30 insertions(+)
 create mode 100644 test/box-luatest/gh_10265_memtx_checkpoint_fail_assertion_test.lua

diff --git a/src/box/memtx_engine.cc b/src/box/memtx_engine.cc
index 0a9051d841..192595c68f 100644
--- a/src/box/memtx_engine.cc
+++ b/src/box/memtx_engine.cc
@@ -1132,6 +1132,8 @@ static void
 memtx_engine_abort_checkpoint(struct engine *engine)
 {
 	struct memtx_engine *memtx = (struct memtx_engine *)engine;
+	if (memtx->checkpoint == NULL)
+		return;
 
 	/**
 	 * An error in the other engine's first phase.
diff --git a/test/box-luatest/gh_10265_memtx_checkpoint_fail_assertion_test.lua b/test/box-luatest/gh_10265_memtx_checkpoint_fail_assertion_test.lua
new file mode 100644
index 0000000000..60cc7f9a90
--- /dev/null
+++ b/test/box-luatest/gh_10265_memtx_checkpoint_fail_assertion_test.lua
@@ -0,0 +1,28 @@
+local t = require('luatest')
+local server = require('luatest.server')
+
+local g = t.group()
+
+g.before_all(function(cg)
+    t.tarantool.skip_if_not_debug()
+    cg.server = server:new()
+    cg.server:start()
+end)
+
+g.after_all(function(cg)
+    cg.server:drop()
+end)
+
+g.test_memtx_checkpoint_fail_assertion = function(cg)
+    cg.server:exec(function()
+        local s = box.schema.space.create('test')
+        s:create_index('pk')
+        s:replace{0, 0}
+        -- Set error injection to iterator creation to fail
+        -- memtx checkpoint right from the start.
+        box.error.injection.set('ERRINJ_INDEX_ITERATOR_NEW', true)
+        local ok = pcall(box.snapshot)
+        box.error.injection.set('ERRINJ_INDEX_ITERATOR_NEW', false)
+        t.assert_equals(ok, false, "Snapshot must fail")
+    end)
+end
-- 
GitLab