diff options
-rw-r--r-- | jstests/replsets/uninitialized_fcv_access.js | 32 | ||||
-rw-r--r-- | src/mongo/base/error_codes.err | 1 | ||||
-rw-r--r-- | src/mongo/db/commands/feature_compatibility_version.cpp | 4 |
3 files changed, 37 insertions, 0 deletions
diff --git a/jstests/replsets/uninitialized_fcv_access.js b/jstests/replsets/uninitialized_fcv_access.js new file mode 100644 index 00000000000..f4cdfae7674 --- /dev/null +++ b/jstests/replsets/uninitialized_fcv_access.js @@ -0,0 +1,32 @@ +/** + * Test that attempting to call getParameter on the featureCompatibilityVersion before the fCV is + * initialized does not crash the server (see SERVER-34600). + */ +(function() { + 'use strict'; + load('jstests/libs/feature_compatibility_version.js'); + + let rst = new ReplSetTest({nodes: 2}); + rst.startSet(); + let node = rst.nodes[0]; + + // The featureCompatibilityVersion parameter is initialized during rst.initiate(), so calling + // getParameter on the fCV before then will attempt to access an uninitialized fCV. + + const getParamCmd = {getParameter: 1, featureCompatibilityVersion: 1}; + assert.commandFailedWithCode(node.getDB('admin').runCommand(getParamCmd), + ErrorCodes.UnknownFeatureCompatibilityVersion, + 'expected ' + tojson(getParamCmd) + + ' to fail with code UnknownFeatureCompatibilityVersion'); + + rst.initiate(); + + // After the replica set is initialized, getParameter should successfully return the fCV. + + const primary = rst.getPrimary(); + const res = primary.adminCommand(getParamCmd); + assert.commandWorked(res); + assert.eq(res.featureCompatibilityVersion.version, latestFCV, tojson(res)); + + rst.stopSet(); +})(); diff --git a/src/mongo/base/error_codes.err b/src/mongo/base/error_codes.err index 023bd887318..dceb57de618 100644 --- a/src/mongo/base/error_codes.err +++ b/src/mongo/base/error_codes.err @@ -255,6 +255,7 @@ error_code("FreeMonHttpTemporaryFailure", 254) error_code("FreeMonHttpPermanentFailure", 255) error_code("TransactionCommitted", 256) error_code("TransactionTooLarge", 257) +error_code("UnknownFeatureCompatibilityVersion", 258); # Error codes 4000-8999 are reserved. diff --git a/src/mongo/db/commands/feature_compatibility_version.cpp b/src/mongo/db/commands/feature_compatibility_version.cpp index 20935c0a4f2..a387b69d2a0 100644 --- a/src/mongo/db/commands/feature_compatibility_version.cpp +++ b/src/mongo/db/commands/feature_compatibility_version.cpp @@ -289,6 +289,10 @@ public: virtual void append(OperationContext* opCtx, BSONObjBuilder& b, const std::string& name) { BSONObjBuilder featureCompatibilityVersionBuilder(b.subobjStart(name)); + uassert(ErrorCodes::UnknownFeatureCompatibilityVersion, + str::stream() << FeatureCompatibilityVersionParser::kParameterName + << " is not yet known.", + serverGlobalParams.featureCompatibility.isVersionInitialized()); switch (serverGlobalParams.featureCompatibility.getVersion()) { case ServerGlobalParams::FeatureCompatibility::Version::kFullyUpgradedTo40: featureCompatibilityVersionBuilder.append( |