From 991853fa55a749d28d6f9e507ce72b289df92785 Mon Sep 17 00:00:00 2001 From: bitflash-maintainer Date: Sun, 23 Aug 2026 11:56:31 +0000 Subject: payout: qualify the single-writer claim for pool_status.json The comment justifying the absence of a version guard said RefreshStats "runs only on the event loop". That was true when it was written and is no longer: the payout-ledger self-test drives RefreshStats directly, to check that no payout mutex is held across the write. The conclusion still holds -- the test calls it from one thread at a time with the pool not running, so pool_status.json still has a single writer -- but the reason a reader would check is now stated, along with what would invalidate it. A claim in a comment that has quietly stopped being true is how 33f2e8a came to assert that no thread waits on I/O holding gPayoutLedgerMutex on the commit that made it do so. Property: comment only. --- src/rpc.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'src/rpc.cpp') diff --git a/src/rpc.cpp b/src/rpc.cpp index 79947df..7a6b6a4 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -2429,11 +2429,18 @@ static std::string SerializePoolStatusLocked() // Publish the operator status file. Call with every payout mutex released. // // Still no version guard and no write mutex, deliberately, and the split does -// not change the argument: RefreshStats remains the only caller, it still runs -// only on the event loop, and it now calls this after leaving the scope that -// serialised -- so the serialise and the write stay strictly ordered on one -// thread and pool_status.json still has a single writer by construction. It -// shares WriteFileAtomic so the durability rules stay in one place. +// not change the argument: RefreshStats remains the only caller of either +// half, in production it runs only on the event loop, and it now calls this +// after leaving the scope that serialised -- so the serialise and the write +// stay strictly ordered on one thread and pool_status.json still has a single +// writer by construction. It shares WriteFileAtomic so the durability rules +// stay in one place. +// +// "In production" is doing real work in that sentence. The payout-ledger +// self-test also calls RefreshStats, from one thread at a time and with the +// pool not running, which is why it is still a single writer there too. A +// second concurrent caller anywhere would invalidate this paragraph and want +// the same versioned publish the ledgers use. static void PublishPoolStatus(const std::string& blob) { WriteFileAtomic(PoolStatusFilePath(), blob, "pool status"); -- cgit v1.2.3