From ed03c3985d1fc73b71fca8f0ab2a2301eba12675 Mon Sep 17 00:00:00 2001 From: Lily Ballard Date: Sun, 16 Feb 2025 22:27:33 -0800 Subject: [PATCH] libstore: use monotonic clock for SQLITE_BUSY warnings Using time_t meant a warning could be printed arbitrarily soon depending on when the second rolled over relative to when the SQLite transaction was attempted. Change-Id: I93401aea65f90e37cd450a293c4dd4d64fba7628 --- lix/libstore/sqlite.cc | 10 +++++----- lix/libstore/sqlite.hh | 9 +++++---- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/lix/libstore/sqlite.cc b/lix/libstore/sqlite.cc index 666d12945..8b19c18f7 100644 --- a/lix/libstore/sqlite.cc +++ b/lix/libstore/sqlite.cc @@ -278,11 +278,11 @@ void SQLiteTxn::Rollback::operator()(sqlite3 * db) } [[nodiscard]] -static std::chrono::milliseconds handleSQLiteBusyCommon(const SQLiteBusy & e, time_t & nextWarning) +static std::chrono::milliseconds handleSQLiteBusyCommon(const SQLiteBusy & e, std::chrono::time_point & nextWarning) { - time_t now = time(0); + auto now = std::chrono::steady_clock::now(); if (now > nextWarning) { - nextWarning = now + 10; + nextWarning = now + std::chrono::seconds(10); logWarning({ .msg = HintFmt(e.what()) }); @@ -297,12 +297,12 @@ static std::chrono::milliseconds handleSQLiteBusyCommon(const SQLiteBusy & e, ti return std::chrono::milliseconds { uniform_dist(generator) }; } -void handleSQLiteBusy(const SQLiteBusy & e, time_t & nextWarning) +void handleSQLiteBusy(const SQLiteBusy & e, std::chrono::time_point & nextWarning) { std::this_thread::sleep_for(handleSQLiteBusyCommon(e, nextWarning)); } -kj::Promise> handleSQLiteBusyAsync(const SQLiteBusy & e, time_t & nextWarning) +kj::Promise> handleSQLiteBusyAsync(const SQLiteBusy & e, std::chrono::time_point & nextWarning) try { std::chrono::milliseconds delay_ms = handleSQLiteBusyCommon(e, nextWarning); co_await AIO().provider.getTimer().afterDelay(delay_ms.count() * kj::MILLISECONDS); diff --git a/lix/libstore/sqlite.hh b/lix/libstore/sqlite.hh index 75f8681e8..e4122e957 100644 --- a/lix/libstore/sqlite.hh +++ b/lix/libstore/sqlite.hh @@ -1,6 +1,7 @@ #pragma once ///@file +#include #include #include #include @@ -190,8 +191,8 @@ protected: MakeError(SQLiteBusy, SQLiteError); -void handleSQLiteBusy(const SQLiteBusy & e, time_t & nextWarning); -kj::Promise> handleSQLiteBusyAsync(const SQLiteBusy & e, time_t & nextWarning); +void handleSQLiteBusy(const SQLiteBusy & e, std::chrono::time_point & nextWarning); +kj::Promise> handleSQLiteBusyAsync(const SQLiteBusy & e, std::chrono::time_point & nextWarning); /** * Convenience function for retrying a SQLite transaction when the @@ -200,10 +201,10 @@ kj::Promise> handleSQLiteBusyAsync(const SQLiteBusy & e, time_t & n template auto retrySQLite(F fun) { - time_t nextWarning = time(0) + 1; + auto nextWarning = std::chrono::steady_clock::now() + std::chrono::seconds(1); if constexpr (requires (F f) { [](kj::Promise>){}(f()); }) { - return [](time_t nextWarning, F fun) -> decltype(fun()) { + return [](std::chrono::time_point nextWarning, F fun) -> decltype(fun()) { while (true) { kj::Promise> handleBusy{nullptr}; try {