diff options
Diffstat (limited to 'src/mongo/util')
-rw-r--r-- | src/mongo/util/assert_util.cpp | 24 | ||||
-rw-r--r-- | src/mongo/util/assert_util.h | 35 | ||||
-rw-r--r-- | src/mongo/util/dns_query.cpp | 4 | ||||
-rw-r--r-- | src/mongo/util/dns_query_posix-impl.h | 18 | ||||
-rw-r--r-- | src/mongo/util/dns_query_windows-impl.h | 10 | ||||
-rw-r--r-- | src/mongo/util/net/socket_exception.cpp | 2 | ||||
-rw-r--r-- | src/mongo/util/net/socket_exception.h | 4 | ||||
-rw-r--r-- | src/mongo/util/options_parser/option_description.cpp | 28 | ||||
-rw-r--r-- | src/mongo/util/options_parser/option_section.cpp | 8 | ||||
-rw-r--r-- | src/mongo/util/options_parser/value.h | 2 |
10 files changed, 79 insertions, 56 deletions
diff --git a/src/mongo/util/assert_util.cpp b/src/mongo/util/assert_util.cpp index b1433b0e3b4..bd1bc9f986a 100644 --- a/src/mongo/util/assert_util.cpp +++ b/src/mongo/util/assert_util.cpp @@ -55,6 +55,22 @@ using namespace std; namespace mongo { +namespace { + +/** + * This type is used for all exceptions that don't have a more specific type. It is defined locally + * in this file to prevent anyone from catching it specifically separately from AssertionException. + */ +class NonspecificAssertionException final : public AssertionException { +public: + using AssertionException::AssertionException; + +private: + void defineOnlyInFinalSubclassToPreventSlicing() final {} +}; + +} // namespace + AssertionCount assertionCount; AssertionCount::AssertionCount() : regular(0), warning(0), msg(0), user(0), rollovers(0) {} @@ -113,14 +129,14 @@ NOINLINE_DECL void verifyFailed(const char* expr, const char* file, unsigned lin logContext(); stringstream temp; temp << "assertion " << file << ":" << line; - AssertionException e(0, temp.str()); + breakpoint(); #if defined(MONGO_CONFIG_DEBUG_BUILD) // this is so we notice in buildbot severe() << "\n\n***aborting after verify() failure as this is a debug/test build\n\n" << endl; std::abort(); #endif - throw e; + throw NonspecificAssertionException(ErrorCodes::UnknownError, temp.str()); } NOINLINE_DECL void invariantFailed(const char* expr, const char* file, unsigned line) noexcept { @@ -186,7 +202,7 @@ NOINLINE_DECL void uassertedWithLocation(int msgid, assertionCount.condrollover(++assertionCount.user); LOG(1) << "User Assertion: " << msgid << ":" << redact(msg) << ' ' << file << ' ' << dec << line << endl; - throw AssertionException(msgid, msg); + throw NonspecificAssertionException(msgid, msg); } NOINLINE_DECL void msgassertedWithLocation(int msgid, @@ -196,7 +212,7 @@ NOINLINE_DECL void msgassertedWithLocation(int msgid, assertionCount.condrollover(++assertionCount.msg); error() << "Assertion: " << msgid << ":" << redact(msg) << ' ' << file << ' ' << dec << line << endl; - throw AssertionException(msgid, msg); + throw NonspecificAssertionException(msgid, msg); } std::string causedBy(StringData e) { diff --git a/src/mongo/util/assert_util.h b/src/mongo/util/assert_util.h index ac8713f4b22..d562799a47e 100644 --- a/src/mongo/util/assert_util.h +++ b/src/mongo/util/assert_util.h @@ -65,15 +65,7 @@ std::string causedBy(const std::string& e); /** Most mongo exceptions inherit from this; this is commonly caught in most threads */ class DBException : public std::exception { public: - DBException(const Status& status) : _status(status) { - invariant(!status.isOK()); - traceIfNeeded(*this); - } - DBException(int code, StringData msg) - : DBException(Status(code ? ErrorCodes::fromInt(code) : ErrorCodes::UnknownError, msg)) {} - virtual ~DBException() throw() {} - - virtual const char* what() const throw() { + const char* what() const throw() final { return reason().c_str(); } @@ -100,13 +92,30 @@ public: return _status.code(); } -private: - static void traceIfNeeded(const DBException& e); + std::string codeString() const { + return _status.codeString(); + } -public: static AtomicBool traceExceptions; protected: + DBException(const Status& status) : _status(status) { + invariant(!status.isOK()); + traceIfNeeded(*this); + } + + DBException(int code, StringData msg) + : DBException(Status(code ? ErrorCodes::fromInt(code) : ErrorCodes::UnknownError, msg)) {} + +private: + static void traceIfNeeded(const DBException& e); + + /** + * This method exists only to make all non-final types in this hierarchy abstract to prevent + * accidental slicing. + */ + virtual void defineOnlyInFinalSubclassToPreventSlicing() = 0; + Status _status; }; @@ -114,8 +123,6 @@ class AssertionException : public DBException { public: AssertionException(const Status& status) : DBException(status) {} AssertionException(int code, StringData msg) : DBException(code, msg) {} - - virtual ~AssertionException() throw() {} }; MONGO_COMPILER_NORETURN void verifyFailed(const char* expr, const char* file, unsigned line); diff --git a/src/mongo/util/dns_query.cpp b/src/mongo/util/dns_query.cpp index 9ce9e8743c6..3eef7240851 100644 --- a/src/mongo/util/dns_query.cpp +++ b/src/mongo/util/dns_query.cpp @@ -67,8 +67,8 @@ std::vector<std::string> dns::lookupARecords(const std::string& service) { auto response = dnsQuery.lookup(service, DNSQueryClass::kInternet, DNSQueryType::kAddress); if (response.size() == 0) { - throw DBException(ErrorCodes::DNSProtocolError, - "Looking up " + service + " A record yielded no results."); + uasserted(ErrorCodes::DNSProtocolError, + "Looking up " + service + " A record yielded no results."); } std::vector<std::string> rv; diff --git a/src/mongo/util/dns_query_posix-impl.h b/src/mongo/util/dns_query_posix-impl.h index 259135e2735..d19958010c8 100644 --- a/src/mongo/util/dns_query_posix-impl.h +++ b/src/mongo/util/dns_query_posix-impl.h @@ -100,15 +100,13 @@ public: std::vector<std::string> txtEntry() const { const auto data = this->_rawData(); if (data.empty()) { - throw DBException(ErrorCodes::DNSProtocolError, - "DNS TXT Record is not correctly sized"); + uasserted(ErrorCodes::DNSProtocolError, "DNS TXT Record is not correctly sized"); } const std::size_t amount = data.front(); const auto first = begin(data) + 1; std::vector<std::string> rv; if (data.size() - 1 < amount) { - throw DBException(ErrorCodes::DNSProtocolError, - "DNS TXT Record is not correctly sized"); + uasserted(ErrorCodes::DNSProtocolError, "DNS TXT Record is not correctly sized"); } rv.emplace_back(first, first + amount); return rv; @@ -122,7 +120,7 @@ public: auto data = _rawData(); if (data.size() != 4) { - throw DBException(ErrorCodes::DNSProtocolError, "DNS A Record is not correctly sized"); + uasserted(ErrorCodes::DNSProtocolError, "DNS A Record is not correctly sized"); } for (const std::uint8_t& ch : data) { std::ostringstream oss; @@ -145,7 +143,7 @@ public: std::ostringstream oss; oss << "Invalid record " << this->_pos << " of SRV answer for \"" << this->_service << "\": Incorrect result size"; - throw DBException(ErrorCodes::DNSProtocolError, oss.str()); + uasserted(ErrorCodes::DNSProtocolError, oss.str()); } const std::uint16_t port = [data] { std::uint16_t tmp; @@ -180,7 +178,7 @@ private: std::ostringstream oss; oss << "Invalid record " << this->_pos << " of DNS answer for \"" << this->_service << "\": \"" << strerror(errno) << "\""; - throw DBException(ErrorCodes::DNSProtocolError, oss.str()); + uasserted(ErrorCodes::DNSProtocolError, oss.str()); }; std::vector<std::uint8_t> _rawData() const { @@ -208,7 +206,7 @@ public: if (ns_initparse(this->_data.data(), this->_data.size(), &this->_ns_answer)) { std::ostringstream oss; oss << "Invalid SRV answer for \"" << this->_service << "\""; - throw DBException(ErrorCodes::DNSProtocolError, oss.str()); + uasserted(ErrorCodes::DNSProtocolError, oss.str()); } this->_nRecords = ns_msg_count(this->_ns_answer, ns_s_an); @@ -216,7 +214,7 @@ public: if (!this->_nRecords) { std::ostringstream oss; oss << "No SRV records for \"" << this->_service << "\""; - throw DBException(ErrorCodes::DNSProtocolError, oss.str()); + uasserted(ErrorCodes::DNSProtocolError, oss.str()); } } @@ -322,7 +320,7 @@ public: if (size < 0) { std::ostringstream oss; oss << "Failed to look up service \"" << service << "\": " << strerror(errno); - throw DBException(ErrorCodes::DNSHostNotFound, oss.str()); + uasserted(ErrorCodes::DNSHostNotFound, oss.str()); } result.resize(size); diff --git a/src/mongo/util/dns_query_windows-impl.h b/src/mongo/util/dns_query_windows-impl.h index 04fe778c5eb..974cb558efe 100644 --- a/src/mongo/util/dns_query_windows-impl.h +++ b/src/mongo/util/dns_query_windows-impl.h @@ -81,7 +81,7 @@ public: std::ostringstream oss; oss << "Incorrect record format for \"" << this->_service << "\": expected TXT record, found something else"; - throw DBException(ErrorCodes::DNSProtocolError, oss.str()); + uasserted(ErrorCodes::DNSProtocolError, oss.str()); } std::vector<std::string> rv; @@ -100,7 +100,7 @@ public: std::ostringstream oss; oss << "Incorrect record format for \"" << this->_service << "\": expected A record, found something else"; - throw DBException(ErrorCodes::DNSProtocolError, oss.str()); + uasserted(ErrorCodes::DNSProtocolError, oss.str()); } std::string rv; @@ -124,7 +124,7 @@ public: std::ostringstream oss; oss << "Incorrect record format for \"" << this->_service << "\": expected SRV record, found something else"; - throw DBException(ErrorCodes::DNSProtocolError, oss.str()); + uasserted(ErrorCodes::DNSProtocolError, oss.str()); } const auto& data = this->_record->Data.SRV; @@ -244,8 +244,8 @@ public: nullptr); if (ec) { - throw DBException(ErrorCodes::DNSHostNotFound, - "Failed to look up service \""s + "\":"s + errnoWithDescription(ec)); + uasserted(ErrorCodes::DNSHostNotFound, + "Failed to look up service \""s + "\":"s + errnoWithDescription(ec)); } return DNSResponse{queryResults}; } diff --git a/src/mongo/util/net/socket_exception.cpp b/src/mongo/util/net/socket_exception.cpp index 88b75fd1873..522fc8b960f 100644 --- a/src/mongo/util/net/socket_exception.cpp +++ b/src/mongo/util/net/socket_exception.cpp @@ -75,7 +75,7 @@ bool SocketException::shouldPrint() const { std::string SocketException::toString() const { std::stringstream ss; - ss << _status.codeString() << " socket exception [" << getStringType(_type) << "] "; + ss << codeString() << " socket exception [" << getStringType(_type) << "] "; if (_server.size()) ss << "server [" << _server << "] "; diff --git a/src/mongo/util/net/socket_exception.h b/src/mongo/util/net/socket_exception.h index b610e754bb3..e6e5ac25c2d 100644 --- a/src/mongo/util/net/socket_exception.h +++ b/src/mongo/util/net/socket_exception.h @@ -37,7 +37,7 @@ namespace mongo { /** * A special class of DBException thrown by Sockets. */ -class SocketException : public DBException { +class SocketException final : public DBException { public: const enum Type { CLOSED, @@ -61,6 +61,8 @@ public: std::string toString() const override; private: + void defineOnlyInFinalSubclassToPreventSlicing() final {} + std::string _server; std::string _extra; }; diff --git a/src/mongo/util/options_parser/option_description.cpp b/src/mongo/util/options_parser/option_description.cpp index 857b359b6b7..ae0b22965af 100644 --- a/src/mongo/util/options_parser/option_description.cpp +++ b/src/mongo/util/options_parser/option_description.cpp @@ -128,14 +128,14 @@ OptionDescription::OptionDescription(const std::string& dottedName, if (std::count(_deprecatedDottedNames.begin(), _deprecatedDottedNames.end(), "")) { StringBuilder sb; sb << "Attempted to register option with empty string for deprecated dotted name"; - throw DBException(ErrorCodes::BadValue, sb.str()); + uasserted(ErrorCodes::BadValue, sb.str()); } // Should not be the same as _dottedName. if (std::count(_deprecatedDottedNames.begin(), _deprecatedDottedNames.end(), dottedName)) { StringBuilder sb; sb << "Attempted to register option with conflict between dottedName and deprecated " << "dotted name: " << _dottedName; - throw DBException(ErrorCodes::BadValue, sb.str()); + uasserted(ErrorCodes::BadValue, sb.str()); } } @@ -151,7 +151,7 @@ OptionDescription& OptionDescription::setDefault(Value defaultValue) { StringBuilder sb; sb << "Could not register option \"" << _dottedName << "\": " << "Cannot register a default value for a composing option"; - throw DBException(ErrorCodes::InternalError, sb.str()); + uasserted(ErrorCodes::InternalError, sb.str()); } // Make sure the type of our default value matches our declared type @@ -160,7 +160,7 @@ OptionDescription& OptionDescription::setDefault(Value defaultValue) { StringBuilder sb; sb << "Could not register option \"" << _dottedName << "\": " << "mismatch between declared type and type of default value: " << ret.toString(); - throw DBException(ErrorCodes::InternalError, sb.str()); + uasserted(ErrorCodes::InternalError, sb.str()); } _default = defaultValue; @@ -174,7 +174,7 @@ OptionDescription& OptionDescription::setImplicit(Value implicitValue) { StringBuilder sb; sb << "Could not register option \"" << _dottedName << "\": " << "Cannot register an implicit value for a composing option"; - throw DBException(ErrorCodes::InternalError, sb.str()); + uasserted(ErrorCodes::InternalError, sb.str()); } // Make sure the type of our implicit value matches our declared type @@ -183,7 +183,7 @@ OptionDescription& OptionDescription::setImplicit(Value implicitValue) { StringBuilder sb; sb << "Could not register option \"" << _dottedName << "\": " << "mismatch between declared type and type of implicit value: " << ret.toString(); - throw DBException(ErrorCodes::InternalError, sb.str()); + uasserted(ErrorCodes::InternalError, sb.str()); } // It doesn't make sense to set an "implicit value" for switch options since they can never @@ -192,7 +192,7 @@ OptionDescription& OptionDescription::setImplicit(Value implicitValue) { StringBuilder sb; sb << "Could not register option \"" << _dottedName << "\": " << "the implicit value of a Switch option is true and cannot be changed"; - throw DBException(ErrorCodes::InternalError, sb.str()); + uasserted(ErrorCodes::InternalError, sb.str()); } _implicit = implicitValue; @@ -204,7 +204,7 @@ OptionDescription& OptionDescription::composing() { StringBuilder sb; sb << "Could not register option \"" << _dottedName << "\": " << "only options registered as StringVector or StringMap can be composing"; - throw DBException(ErrorCodes::InternalError, sb.str()); + uasserted(ErrorCodes::InternalError, sb.str()); } // Disallow registering a default value for a composing option since the interaction @@ -213,7 +213,7 @@ OptionDescription& OptionDescription::composing() { StringBuilder sb; sb << "Could not register option \"" << _dottedName << "\": " << "Cannot make an option with an default value composing"; - throw DBException(ErrorCodes::InternalError, sb.str()); + uasserted(ErrorCodes::InternalError, sb.str()); } // Disallow registering an implicit value for a composing option since the interaction @@ -222,7 +222,7 @@ OptionDescription& OptionDescription::composing() { StringBuilder sb; sb << "Could not register option \"" << _dottedName << "\": " << "Cannot make an option with an implicit value composing"; - throw DBException(ErrorCodes::InternalError, sb.str()); + uasserted(ErrorCodes::InternalError, sb.str()); } _isComposing = true; @@ -239,7 +239,7 @@ OptionDescription& OptionDescription::positional(int start, int end) { StringBuilder sb; sb << "Could not register option \"" << _dottedName << "\": " << "Invalid positional specification: \"start\": " << start << ", \"end\": " << end; - throw DBException(ErrorCodes::InternalError, sb.str()); + uasserted(ErrorCodes::InternalError, sb.str()); } if ((end - start) > 0) { @@ -248,7 +248,7 @@ OptionDescription& OptionDescription::positional(int start, int end) { sb << "Could not register option \"" << _dottedName << "\": " << "Positional range implies that multiple values are allowed, " << "but option is not registered as type StringVector"; - throw DBException(ErrorCodes::InternalError, sb.str()); + uasserted(ErrorCodes::InternalError, sb.str()); } } @@ -269,7 +269,7 @@ OptionDescription& OptionDescription::validRange(long min, long max) { sb << "Could not register option \"" << _dottedName << "\": " << "only options registered as a numeric type can have a valid range, " << "but option has type: " << _type; - throw DBException(ErrorCodes::InternalError, sb.str()); + uasserted(ErrorCodes::InternalError, sb.str()); } return addConstraint(new NumericKeyConstraint(_dottedName, min, max)); @@ -290,7 +290,7 @@ OptionDescription& OptionDescription::format(const std::string& regexFormat, sb << "Could not register option \"" << _dottedName << "\": " << "only options registered as a string type can have a required format, " << "but option has type: " << _type; - throw DBException(ErrorCodes::InternalError, sb.str()); + uasserted(ErrorCodes::InternalError, sb.str()); } return addConstraint(new StringFormatKeyConstraint(_dottedName, regexFormat, displayFormat)); diff --git a/src/mongo/util/options_parser/option_section.cpp b/src/mongo/util/options_parser/option_section.cpp index 4bdbb1e28c1..ff77ab0be10 100644 --- a/src/mongo/util/options_parser/option_section.cpp +++ b/src/mongo/util/options_parser/option_section.cpp @@ -90,14 +90,14 @@ OptionDescription& OptionSection::addOptionChaining( if (option._dottedName == oditerator->_dottedName) { StringBuilder sb; sb << "Attempted to register option with duplicate dottedName: " << option._dottedName; - throw DBException(ErrorCodes::InternalError, sb.str()); + uasserted(ErrorCodes::InternalError, sb.str()); } // Allow options with empty singleName since some options are not allowed on the command // line if (!option._singleName.empty() && option._singleName == oditerator->_singleName) { StringBuilder sb; sb << "Attempted to register option with duplicate singleName: " << option._singleName; - throw DBException(ErrorCodes::InternalError, sb.str()); + uasserted(ErrorCodes::InternalError, sb.str()); } // Deprecated dotted names should not conflict with dotted names or deprecated dotted // names of any other options. @@ -107,7 +107,7 @@ OptionDescription& OptionSection::addOptionChaining( StringBuilder sb; sb << "Attempted to register option with duplicate deprecated dotted name " << "(with another option's dotted name): " << option._dottedName; - throw DBException(ErrorCodes::BadValue, sb.str()); + uasserted(ErrorCodes::BadValue, sb.str()); } for (std::vector<std::string>::const_iterator i = oditerator->_deprecatedDottedNames.begin(); @@ -119,7 +119,7 @@ OptionDescription& OptionSection::addOptionChaining( StringBuilder sb; sb << "Attempted to register option with duplicate deprecated dotted name " << *i << " (other option " << oditerator->_dottedName << ")"; - throw DBException(ErrorCodes::BadValue, sb.str()); + uasserted(ErrorCodes::BadValue, sb.str()); } } } diff --git a/src/mongo/util/options_parser/value.h b/src/mongo/util/options_parser/value.h index 42818f60f2b..73880f63d61 100644 --- a/src/mongo/util/options_parser/value.h +++ b/src/mongo/util/options_parser/value.h @@ -171,7 +171,7 @@ T Value::as() const { if (!ret.isOK()) { StringBuilder message; message << "failed to extract typed value from Value container: " << ret.toString(); - throw AssertionException(17114, message.str()); + uasserted(17114, message.str()); } return valueType; |