From a45e6878f39cdc777c54e5d6749d53c1f70e2b52 Mon Sep 17 00:00:00 2001 From: Qingping Wang Date: Mon, 10 Oct 2022 09:46:09 -0700 Subject: [PATCH] fix issue 10751 (#10765) Summary: Fix https://github.com/facebook/rocksdb/issues/10751 where a stalled write could be blocked forever when DB shutdown. Pull Request resolved: https://github.com/facebook/rocksdb/pull/10765 Reviewed By: ajkr Differential Revision: D40110069 Pulled By: ajkr fbshipit-source-id: 598c05777db9be85913a0a85e421b3295ecdff5e --- db/db_impl/db_impl_write.cc | 13 ++++++++---- db/db_test.cc | 40 +++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/db/db_impl/db_impl_write.cc b/db/db_impl/db_impl_write.cc index fc7495cf0..635f16f01 100644 --- a/db/db_impl/db_impl_write.cc +++ b/db/db_impl/db_impl_write.cc @@ -1796,7 +1796,8 @@ Status DBImpl::DelayWrite(uint64_t num_bytes, // might wait here indefinitely as the background compaction may never // finish successfully, resulting in the stall condition lasting // indefinitely - while (error_handler_.GetBGError().ok() && write_controller_.IsStopped()) { + while (error_handler_.GetBGError().ok() && write_controller_.IsStopped() && + !shutting_down_.load(std::memory_order_relaxed)) { if (write_options.no_slowdown) { return Status::Incomplete("Write stall"); } @@ -1822,9 +1823,13 @@ Status DBImpl::DelayWrite(uint64_t num_bytes, // proceed Status s; if (write_controller_.IsStopped()) { - // If writes are still stopped, it means we bailed due to a background - // error - s = Status::Incomplete(error_handler_.GetBGError().ToString()); + if (!shutting_down_.load(std::memory_order_relaxed)) { + // If writes are still stopped and db not shutdown, it means we bailed + // due to a background error + s = Status::Incomplete(error_handler_.GetBGError().ToString()); + } else { + s = Status::ShutdownInProgress("stalled writes"); + } } if (error_handler_.IsDBStopped()) { s = error_handler_.GetBGError(); diff --git a/db/db_test.cc b/db/db_test.cc index 7de55a82b..a22a42b3c 100644 --- a/db/db_test.cc +++ b/db/db_test.cc @@ -7211,6 +7211,46 @@ TEST_F(DBTest, MemoryUsageWithMaxWriteBufferSizeToMaintain) { } } +TEST_F(DBTest, ShuttingDownNotBlockStalledWrites) { + Options options = CurrentOptions(); + options.disable_auto_compactions = true; + Reopen(options); + Random rnd(403); + + ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack( + "BackgroundCallCompaction:1", + [&](void* /* arg */) { env_->SleepForMicroseconds(2 * 1000 * 1000); }); + + ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->LoadDependency( + {{"DBImpl::DelayWrite:Wait", + "DBTest::ShuttingDownNotBlockStalledWrites"}}); + + ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing(); + + for (int i = 0; i < 20; i++) { + for (int j = 0; j < 100; j++) { + std::string value = rnd.RandomString(1000); + ASSERT_OK(Put("key_" + std::to_string(j), value)); + } + Flush(); + } + ASSERT_EQ(GetSstFileCount(dbname_), 20); + + options.level0_stop_writes_trigger = 20; + options.disable_auto_compactions = false; + Reopen(options); + + std::thread thd([&]() { + Status s = Put("key_" + std::to_string(101), "101"); + ASSERT_EQ(s.code(), Status::kShutdownInProgress); + }); + + TEST_SYNC_POINT("DBTest::ShuttingDownNotBlockStalledWrites"); + CancelAllBackgroundWork(db_, true); + LogFlush(options.info_log); + + thd.join(); +} #endif } // namespace ROCKSDB_NAMESPACE