Skip to content

Commit 297241e

Browse files
committed
Fix deadlock in WAL sync
Summary: MarkLogsSynced() was doing `logs_.erase(it++);`. The standard is saying: ``` all iterators and references are invalidated, unless the erased members are at an end (front or back) of the deque (in which case only iterators and references to the erased members are invalidated) ``` Because `it` is an iterator to the first element of the container, it is invalidated, only one iteration is executed and `log.getting_synced = false;` is not being done, so `while (logs_.front().getting_synced)` in `WriteImpl()` is not terminating. Test Plan: make db_bench && ./db_bench --benchmarks=fillsync Reviewers: igor, rven, IslamAbdelRahman, anthony, kradhakrishnan, yhchiang, sdong, tnovak Reviewed By: tnovak Subscribers: kolmike, dhruba, leveldb Differential Revision: https://reviews.facebook.net/D45807
1 parent 254c4fb commit 297241e

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

db/db_impl.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2019,12 +2019,13 @@ void DBImpl::MarkLogsSynced(
20192019
assert(log.getting_synced);
20202020
if (status.ok() && logs_.size() > 1) {
20212021
logs_to_free_.push_back(log.ReleaseWriter());
2022-
logs_.erase(it++);
2022+
it = logs_.erase(it);
20232023
} else {
20242024
log.getting_synced = false;
20252025
++it;
20262026
}
20272027
}
2028+
assert(logs_.empty() || (logs_.size() == 1 && !logs_[0].getting_synced));
20282029
log_sync_cv_.SignalAll();
20292030
}
20302031

db/db_test.cc

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4398,6 +4398,30 @@ TEST_F(DBTest, PurgeInfoLogs) {
43984398
}
43994399
}
44004400

4401+
TEST_F(DBTest, SyncMultipleLogs) {
4402+
const uint64_t kNumBatches = 2;
4403+
const int kBatchSize = 1000;
4404+
4405+
Options options = CurrentOptions();
4406+
options.create_if_missing = true;
4407+
options.write_buffer_size = 4096;
4408+
Reopen(options);
4409+
4410+
WriteBatch batch;
4411+
WriteOptions wo;
4412+
wo.sync = true;
4413+
4414+
for (uint64_t b = 0; b < kNumBatches; b++) {
4415+
batch.Clear();
4416+
for (int i = 0; i < kBatchSize; i++) {
4417+
batch.Put(Key(i), DummyString(128));
4418+
}
4419+
4420+
dbfull()->Write(wo, &batch);
4421+
}
4422+
4423+
ASSERT_OK(dbfull()->SyncWAL());
4424+
}
44014425

44024426
//
44034427
// Test WAL recovery for the various modes available

0 commit comments

Comments
 (0)