Details
-
Bug
-
Resolution: Fixed
-
Major - P3
-
None
-
None
-
Fully Compatible
-
ALL
-
v4.4
-
Sharding 2020-03-23
-
30
Description
The serialisation of read/write concern may or may not include the provenance field, depending on the FCV. This means that if FCV is upgraded concurrently, such that one side of the BSON comparison includes provenance but the other doesn't, then the comparison result will be spurious.
The only place this occurs is when making sure that commands don't alter the writeConcern during their runtime:
https://github.com/mongodb/mongo/blob/r4.5.0/src/mongo/db/service_entry_point_common.cpp#L788
// With the exception of getMores inheriting the WriteConcern from the originating command, |
// nothing in run() should change the writeConcern. |
dassert(command->getLogicalOp() == LogicalOp::opGetMore
|
? !extractedWriteConcern
|
: (extractedWriteConcern &&
|
SimpleBSONObjComparator::kInstance.evaluate(
|
opCtx->getWriteConcern().toBSON() == extractedWriteConcern->toBSON())));
|
Possible solutions (in my suggested order of preference):
- Stop doing this comparison via BSON, and instead add a way to properly compare the internal fields of the WriteConcernOptions.
- Add a bool forceProvenance = false parameter to WriteConcernOptions::toBSON(), which is passed as true in these invocations.
- After generating the BSONObjs for comparison, strip out any provenance field from both objects before comparing them.
We should also improve the assertion so that it includes the conflicting writeConcerns in the message when it fails (in the non-opGetMore case).