summaryrefslogtreecommitdiff
path: root/src/mongo/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/util')
-rw-r--r--src/mongo/util/assert_util.cpp24
-rw-r--r--src/mongo/util/assert_util.h35
-rw-r--r--src/mongo/util/dns_query.cpp4
-rw-r--r--src/mongo/util/dns_query_posix-impl.h18
-rw-r--r--src/mongo/util/dns_query_windows-impl.h10
-rw-r--r--src/mongo/util/net/socket_exception.cpp2
-rw-r--r--src/mongo/util/net/socket_exception.h4
-rw-r--r--src/mongo/util/options_parser/option_description.cpp28
-rw-r--r--src/mongo/util/options_parser/option_section.cpp8
-rw-r--r--src/mongo/util/options_parser/value.h2
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;