diff options
author | XueruiFa <xuerui.fa@mongodb.com> | 2020-09-16 16:09:27 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-11-30 20:08:32 +0000 |
commit | dd3d60643b760ee60d9445e4769fa68b35e0eba7 (patch) | |
tree | 25ca5ac89dc72afdede888f1f540b34cd293e9c1 | |
parent | 2b220b6e36f7db4e39f17527acc66f2490a80cca (diff) | |
download | mongo-dd3d60643b760ee60d9445e4769fa68b35e0eba7.tar.gz |
SERVER-49159: Return NotPrimaryOrSecondary if currentTime is uninitialized in waitForReadConcernImpl
(cherry picked from commit 9492de5aac55c8c579044dfa54703056d6012d95)
-rw-r--r-- | src/mongo/db/read_concern_mongod.cpp | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/src/mongo/db/read_concern_mongod.cpp b/src/mongo/db/read_concern_mongod.cpp index b7e8b4cf4de..bce6114e505 100644 --- a/src/mongo/db/read_concern_mongod.cpp +++ b/src/mongo/db/read_concern_mongod.cpp @@ -322,7 +322,23 @@ Status waitForReadConcernImpl(OperationContext* opCtx, << " readConcern without replication enabled"}; } - auto currentTime = LogicalClock::get(opCtx)->getClusterTime(); + // We must read the member state before obtaining the cluster time. Otherwise, we can + // run into a race where the cluster time is read as uninitialized, but the member state + // is set to RECOVERING by another thread before we invariant that the node is in + // STARTUP or STARTUP2. + const auto memberState = replCoord->getMemberState(); + + const auto currentTime = LogicalClock::get(opCtx)->getClusterTime(); + if (currentTime == LogicalTime::kUninitialized) { + // currentTime should only be uninitialized if we are in startup recovery or initial + // sync. + invariant(memberState.startup() || memberState.startup2()); + return {ErrorCodes::NotPrimaryOrSecondary, + str::stream() << "Current clusterTime is uninitialized, cannot service the " + "requested clusterTime. Requested clusterTime: " + << targetClusterTime->toString() + << "; current clusterTime: " << currentTime.toString()}; + } if (currentTime < *targetClusterTime) { return {ErrorCodes::InvalidOptions, str::stream() << "readConcern " << readConcernName |