3.0 KiB
Exception Architecture
MongoDB code uses the following types of assertions that are available for use:
uassert- Checks for per-operation user errors. Operation-fatal.
massert- Checks per-operation invariants. Operation-fatal.
fassert- Checks fatal process invariants. Process-fatal. Use to detect unexpected situations (such as a system function returning an unexpected error status).
invariant- Checks process invariant. Process-fatal. Use to detect code logic errors ("pointer should never be null", "we should always be locked").
Note: Calling C function assert is not allowed. Use one of the above instead.
The following types of assertions are deprecated:
verify- Checks per-operation invariants. A synonym for massert but doesn't require an error code. Do not use for new code; use invariant or fassert instead.
dassert- Calls
verifybut only in debug mode. Do not use!
- Calls
Considerations
When per-operation invariant checks fail, the current operation fails, but the process and
connection persist. This means that massert, uassert and verify only terminate the current
operation, not the whole process. Be careful not to corrupt process state by mistakenly using these
assertions midway through mutating process state. Examples of this include uassert and massert
inside of constructors and destructors.
fassert failures will terminate the entire process; this is used for low-level checks where
continuing might lead to corrupt data or loss of data on disk.
Both massert and uassert take error codes, so that all errors have codes associated with them.
These error codes are assigned incrementally; the numbers have no meaning other than a way to
associate a log message with a line of code. SCons checks for duplicates, but if you want the next
available code you can run:
python buildscripts/errorcodes.py
Exception
A failed operation-fatal assertion throws an AssertionException or a child of that.
The inheritance hierarchy resembles:
std::exceptionmongo::DBExceptionmongo::AssertionExceptionmongo::UserExceptionmongo::MsgAssertionException
See util/assert_util.h.
Generally, code in the server should be prepared to catch a DBException. The code should also
expect UserException. We use Resource Acquisition Is Initialization heavily.
Gotchas
Gotchas to watch out for:
- Generally, do not throw an
AssertionExceptiondirectly. Functions likeuasserted()do work beyond just that. In particular, it makes sure that thegetLastErrorstructures are set up properly. - Think about the location of your asserts in constructors, as the destructor would not be
called. But at a minimum, use
wasserta lot therein, we want to know if something is wrong. - Do not throw in destructors or allow exceptions to leak out (if you call a function that may throw).