summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierlauro Sciarelli <pierlauro.sciarelli@mongodb.com>2020-11-16 18:04:16 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-11-16 19:43:11 +0000
commitaa2b7d3eb58690778f8ea378afaa471beb65d491 (patch)
tree8a5a3a239db5f2fc7103379c2c900a8673cb9486
parente1e8ea257b835c4d8e130205a2fd8297bcccbd47 (diff)
downloadmongo-aa2b7d3eb58690778f8ea378afaa471beb65d491.tar.gz
SERVER-52741 Avoid invariant when trying to get optional ErrorExtraInfo
-rw-r--r--src/mongo/base/status.h18
-rw-r--r--src/mongo/base/status_test.cpp8
-rw-r--r--src/mongo/util/assert_util.h8
3 files changed, 22 insertions, 12 deletions
diff --git a/src/mongo/base/status.h b/src/mongo/base/status.h
index 0b9d1fc1f6e..4d6e332f28a 100644
--- a/src/mongo/base/status.h
+++ b/src/mongo/base/status.h
@@ -168,27 +168,31 @@ public:
/**
* Returns the generic ErrorExtraInfo if present.
*/
- const ErrorExtraInfo* extraInfo() const {
- return isOK() ? nullptr : _error->extra.get();
+ const std::shared_ptr<const ErrorExtraInfo> extraInfo() const {
+ return isOK() ? nullptr : _error->extra;
}
/**
* Returns a specific subclass of ErrorExtraInfo if the error code matches that type.
*/
template <typename T>
- const T* extraInfo() const {
+ std::shared_ptr<const T> extraInfo() const {
MONGO_STATIC_ASSERT(std::is_base_of<ErrorExtraInfo, T>());
MONGO_STATIC_ASSERT(std::is_same<error_details::ErrorExtraInfoFor<T::code>, T>());
if (isOK())
- return nullptr;
+ return {};
if (code() != T::code)
- return nullptr;
+ return {};
+
+ if (!_error->extra) {
+ invariant(!ErrorCodes::mustHaveExtraInfo(_error->code));
+ return {};
+ }
// Can't use checked_cast due to include cycle.
- invariant(_error->extra);
dassert(dynamic_cast<const T*>(_error->extra.get()));
- return static_cast<const T*>(_error->extra.get());
+ return std::static_pointer_cast<const T>(_error->extra);
}
std::string toString() const;
diff --git a/src/mongo/base/status_test.cpp b/src/mongo/base/status_test.cpp
index 73cb1766907..4e2582597bf 100644
--- a/src/mongo/base/status_test.cpp
+++ b/src/mongo/base/status_test.cpp
@@ -326,6 +326,14 @@ TEST(ErrorExtraInfo, OptionalExtraInfoStatusParserWorks) {
ASSERT_EQ(status.extraInfo<OptionalErrorExtraInfoExample>()->data, 123);
}
+TEST(ErrorExtraInfo, MissingOptionalExtraInfoStatus) {
+ OptionalErrorExtraInfoExample::EnableParserForTest whenInScope;
+ const auto status = Status(ErrorCodes::ForTestingOptionalErrorExtraInfo, "");
+ ASSERT_EQ(status, ErrorCodes::ForTestingOptionalErrorExtraInfo);
+ ASSERT_FALSE(status.extraInfo());
+ ASSERT_FALSE(status.extraInfo<OptionalErrorExtraInfoExample>());
+}
+
TEST(ErrorExtraInfo, TypedConstructorWorks) {
const auto status = Status(ErrorExtraInfoExample(123), "");
ASSERT_EQ(status, ErrorCodes::ForTestingErrorExtraInfo);
diff --git a/src/mongo/util/assert_util.h b/src/mongo/util/assert_util.h
index 0e2558cf093..b44dceccafa 100644
--- a/src/mongo/util/assert_util.h
+++ b/src/mongo/util/assert_util.h
@@ -62,8 +62,6 @@ public:
};
extern AssertionCount assertionCount;
-
-
class DBException;
std::string causedBy(const DBException& e);
std::string causedBy(const std::string& e);
@@ -117,7 +115,7 @@ public:
/**
* Returns the generic ErrorExtraInfo if present.
*/
- const ErrorExtraInfo* extraInfo() const {
+ const std::shared_ptr<const ErrorExtraInfo> extraInfo() const {
return _status.extraInfo();
}
@@ -125,7 +123,7 @@ public:
* Returns a specific subclass of ErrorExtraInfo if the error code matches that type.
*/
template <typename ErrorDetail>
- const ErrorDetail* extraInfo() const {
+ std::shared_ptr<const ErrorDetail> extraInfo() const {
return _status.extraInfo<ErrorDetail>();
}
@@ -189,7 +187,7 @@ public:
// This is only a template to enable SFINAE. It will only be instantiated with the default
// value.
template <ErrorCodes::Error code_copy = kCode>
- const ErrorExtraInfoFor<code_copy>* operator->() const {
+ std::shared_ptr<const ErrorExtraInfoFor<code_copy>> operator->() const {
MONGO_STATIC_ASSERT(code_copy == kCode);
return this->template extraInfo<ErrorExtraInfoFor<kCode>>();
}