From: Andres Noetzli Date: Sat, 29 Aug 2015 01:06:32 +0000 (-0700) Subject: Fix deadlock in WAL sync X-Git-Tag: rocksdb-3.13.1~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=297241e056debd50b53fa585f4238dacefb1c4ff;p=rocksdb.git 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 --- diff --git a/db/db_impl.cc b/db/db_impl.cc index 7652a66d..62ab45fb 100644 --- a/db/db_impl.cc +++ b/db/db_impl.cc @@ -2019,12 +2019,13 @@ void DBImpl::MarkLogsSynced( assert(log.getting_synced); if (status.ok() && logs_.size() > 1) { logs_to_free_.push_back(log.ReleaseWriter()); - logs_.erase(it++); + it = logs_.erase(it); } else { log.getting_synced = false; ++it; } } + assert(logs_.empty() || (logs_.size() == 1 && !logs_[0].getting_synced)); log_sync_cv_.SignalAll(); } diff --git a/db/db_test.cc b/db/db_test.cc index 07a0b570..e618f2cc 100644 --- a/db/db_test.cc +++ b/db/db_test.cc @@ -4398,6 +4398,30 @@ TEST_F(DBTest, PurgeInfoLogs) { } } +TEST_F(DBTest, SyncMultipleLogs) { + const uint64_t kNumBatches = 2; + const int kBatchSize = 1000; + + Options options = CurrentOptions(); + options.create_if_missing = true; + options.write_buffer_size = 4096; + Reopen(options); + + WriteBatch batch; + WriteOptions wo; + wo.sync = true; + + for (uint64_t b = 0; b < kNumBatches; b++) { + batch.Clear(); + for (int i = 0; i < kBatchSize; i++) { + batch.Put(Key(i), DummyString(128)); + } + + dbfull()->Write(wo, &batch); + } + + ASSERT_OK(dbfull()->SyncWAL()); +} // // Test WAL recovery for the various modes available