Skip to content
Snippets Groups Projects
Commit 1e73b71d authored by Vladimir Davydov's avatar Vladimir Davydov
Browse files

gc: fix panic if checkpoint_interval is updated during checkpoint

To wait for a thread writing a snap file memtx_engine_wait_checkpoint()
uses cord_cojoin(), which doesn't tolerate spurious wakeups. Hence we
must not wake up the checkpoint fiber after reconfiguring the checkpoint
interval if it's currently making a checkpoint.

Fixes 4c04808a ("Rewrite checkpoint daemon in C").

Closes #3878
parent e6ebd5eb
No related branches found
No related tags found
No related merge requests found
......@@ -311,10 +311,15 @@ gc_set_checkpoint_interval(double interval)
/*
* Reconfigure the schedule and wake up the checkpoint
* daemon so that it can readjust.
*
* Note, we must not wake up the checkpoint daemon fiber
* if it's waiting for checkpointing to complete, because
* checkpointing code doesn't tolerate spurious wakeups.
*/
checkpoint_schedule_cfg(&gc.checkpoint_schedule,
ev_monotonic_now(loop()), interval);
fiber_wakeup(gc.checkpoint_fiber);
if (!gc.checkpoint_is_in_progress)
fiber_wakeup(gc.checkpoint_fiber);
}
void
......
......@@ -85,3 +85,71 @@ test:drop()
errinj = nil
---
...
--
-- gh-3878: Panic when checkpoint_interval is reconfigured while
-- the checkpoint daemon is making a checkpoint.
--
fio = require('fio')
---
...
box.space._schema:delete('test') -- bump LSN
---
...
box.error.injection.set('ERRINJ_SNAP_WRITE_ROW_TIMEOUT', 0.1)
---
- ok
...
default_checkpoint_interval = box.cfg.checkpoint_interval
---
...
box.cfg{checkpoint_interval = 0.01}
---
...
-- Wait for the checkpoint daemon to start making a checkpoint.
test_run:cmd("setopt delimiter ';'")
---
- true
...
test_run:wait_cond(function()
local filename = string.format('%020d.snap.inprogress', box.info.signature)
return fio.path.exists(fio.pathjoin(box.cfg.memtx_dir, filename))
end, 10);
---
- true
...
test_run:cmd("setopt delimiter ''");
---
- true
...
box.cfg{checkpoint_interval = 0.1}
---
...
box.cfg{checkpoint_interval = 1}
---
...
box.cfg{checkpoint_interval = 10}
---
...
box.cfg{checkpoint_interval = default_checkpoint_interval}
---
...
box.error.injection.set('ERRINJ_SNAP_WRITE_ROW_TIMEOUT', 0)
---
- ok
...
-- Wait for the checkpoint daemon to finish making a checkpoint.
test_run:cmd("setopt delimiter ';'")
---
- true
...
test_run:wait_cond(function()
local filename = string.format('%020d.snap', box.info.signature)
return fio.path.exists(fio.pathjoin(box.cfg.memtx_dir, filename))
end, 10);
---
- true
...
test_run:cmd("setopt delimiter ''");
---
- true
...
......@@ -41,3 +41,32 @@ errinj.set('ERRINJ_WAL_WRITE', false)
-- Cleanup
test:drop()
errinj = nil
--
-- gh-3878: Panic when checkpoint_interval is reconfigured while
-- the checkpoint daemon is making a checkpoint.
--
fio = require('fio')
box.space._schema:delete('test') -- bump LSN
box.error.injection.set('ERRINJ_SNAP_WRITE_ROW_TIMEOUT', 0.1)
default_checkpoint_interval = box.cfg.checkpoint_interval
box.cfg{checkpoint_interval = 0.01}
-- Wait for the checkpoint daemon to start making a checkpoint.
test_run:cmd("setopt delimiter ';'")
test_run:wait_cond(function()
local filename = string.format('%020d.snap.inprogress', box.info.signature)
return fio.path.exists(fio.pathjoin(box.cfg.memtx_dir, filename))
end, 10);
test_run:cmd("setopt delimiter ''");
box.cfg{checkpoint_interval = 0.1}
box.cfg{checkpoint_interval = 1}
box.cfg{checkpoint_interval = 10}
box.cfg{checkpoint_interval = default_checkpoint_interval}
box.error.injection.set('ERRINJ_SNAP_WRITE_ROW_TIMEOUT', 0)
-- Wait for the checkpoint daemon to finish making a checkpoint.
test_run:cmd("setopt delimiter ';'")
test_run:wait_cond(function()
local filename = string.format('%020d.snap', box.info.signature)
return fio.path.exists(fio.pathjoin(box.cfg.memtx_dir, filename))
end, 10);
test_run:cmd("setopt delimiter ''");
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment