Swap: fsync without blocking edits; base identity off the lock; races
- The writer's periodic fsync now holds a separate io_mtx_, taken also (before mtx_) by the main-thread paths that close journal fds, instead of mtx_. Every keystroke takes mtx_ to enqueue its record, so a slow fsync (writeback pressure, NFS) froze typing. - A journal's base identity (stat + content CRC) is computed before taking mtx_ and applied under it; the CRC is skipped above 64 MiB (size and mtime still identify the file). It re-read the whole file under the lock on every open and save. - A buffer that was never journaled (a virtual buffer saved under a real name) is attached by NotifyFilenameChanged. - ThreadSanitizer: open_ctx (writer thread) no longer writes ctx.path, and locked_out is recorded by the caller under mtx_; both raced with main-thread reads. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015rcVQiiWyTzoNrsvLSaAfB
This commit is contained in:
@@ -1126,3 +1126,23 @@ TEST(Audit_Save_HardLink_LeftoverCopyDoesNotBlock)
|
||||
ASSERT_TRUE(b.Save(err));
|
||||
ASSERT_EQ(slurp(d.path / "h2.txt"), std::string("new old\n"));
|
||||
}
|
||||
|
||||
|
||||
// A virtual buffer saved under a real name is journaled from then on.
|
||||
TEST(Audit_VirtualBuffer_SavedAs_GetsJournal)
|
||||
{
|
||||
TempDir d("virtual_saveas");
|
||||
TestHarness h;
|
||||
Editor &ed = h.EditorRef();
|
||||
ASSERT_TRUE(h.Exec(CommandId::ShowHelp));
|
||||
ASSERT_TRUE(h.Exec(CommandId::ToggleReadOnly));
|
||||
const std::string target = (d.path / "notes.txt").string();
|
||||
ASSERT_TRUE(Execute(ed, "save-as", target));
|
||||
Buffer *b = ed.CurrentBuffer();
|
||||
ASSERT_TRUE(!b->IsVirtual());
|
||||
ASSERT_TRUE(h.Exec(CommandId::InsertText, "x"));
|
||||
ed.Swap()->Flush(b);
|
||||
const std::string swp = kte::SwapManager::ComputeSwapPathForTests(*b);
|
||||
ASSERT_TRUE(std::filesystem::exists(swp));
|
||||
std::filesystem::remove(swp);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user