diff --git a/changelogs/unreleased/gh-10233-vy-snapshot-hang-fix.md b/changelogs/unreleased/gh-10233-vy-snapshot-hang-fix.md new file mode 100644 index 0000000000000000000000000000000000000000..bf58a263f32d650d3d89f012262ac292d2660c52 --- /dev/null +++ b/changelogs/unreleased/gh-10233-vy-snapshot-hang-fix.md @@ -0,0 +1,4 @@ +## bugfix/vinyl + +* Fixed a bug when `box.snapshot` hanged if executed concurrently with creation + of a new index (gh-10233). diff --git a/src/box/vy_scheduler.c b/src/box/vy_scheduler.c index ea9b438bdb7a7c3f3ce4778898ba18cd3cba7380..29e9c19245c3af1993a5f70d9f39e90182ab5770 100644 --- a/src/box/vy_scheduler.c +++ b/src/box/vy_scheduler.c @@ -670,7 +670,7 @@ vy_scheduler_complete_dump(struct vy_scheduler *scheduler) scheduler->stat.dump_count++; scheduler->dump_complete_cb(scheduler, min_generation - 1, dump_duration); - fiber_cond_signal(&scheduler->dump_cond); + fiber_cond_broadcast(&scheduler->dump_cond); } int @@ -2068,7 +2068,7 @@ vy_scheduler_f(va_list va) continue; error: /* Abort pending checkpoint. */ - fiber_cond_signal(&scheduler->dump_cond); + fiber_cond_broadcast(&scheduler->dump_cond); /* * A task can fail either due to lack of memory or IO * error. In either case it is pointless to schedule diff --git a/test/vinyl-luatest/gh_10233_index_build_vs_snapshot_test.lua b/test/vinyl-luatest/gh_10233_index_build_vs_snapshot_test.lua new file mode 100644 index 0000000000000000000000000000000000000000..3a9ddec7434560580dd6a892a22d209f1c8cb415 --- /dev/null +++ b/test/vinyl-luatest/gh_10233_index_build_vs_snapshot_test.lua @@ -0,0 +1,42 @@ +local server = require('luatest.server') +local t = require('luatest') + +local g = t.group() + +g.before_all(function(cg) + cg.server = server:new() + cg.server:start() +end) + +g.after_all(function(cg) + cg.server:drop() +end) + +g.after_each(function(cg) + cg.server:exec(function() + if box.space.test ~= nil then + box.space.test:drop() + end + end) +end) + +g.test_index_build_vs_snapshot = function(cg) + cg.server:exec(function() + local fiber = require('fiber') + local s = box.schema.space.create('test', {engine = 'vinyl'}) + s:create_index('pk') + s:insert({1, 1}) + local f1 = fiber.new(function() + s:create_index('sk', {parts = {2, 'unsigned'}}) + end) + f1:set_joinable(true) + local f2 = fiber.new(function() + box.snapshot() + end) + f2:set_joinable(true) + fiber.sleep(0.1) + local timeout = 5 + t.assert_equals({f1:join(timeout)}, {true}) + t.assert_equals({f2:join(timeout)}, {true}) + end) +end