diff options
author | Ian Whalen <ian@mongodb.com> | 2020-02-12 12:21:17 -0500 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-03-17 13:12:40 +0000 |
commit | fb26a7fb81b1c6986ebfebbdd9289297fbfd16aa (patch) | |
tree | d9ef620121fe920a02cced87643e7a3a99e77c60 /docs/exception_architecture.md | |
parent | aa1ee1001b9a7ae5822b01c6378402cbc9f1d1e8 (diff) | |
download | mongo-fb26a7fb81b1c6986ebfebbdd9289297fbfd16aa.tar.gz |
SERVER-37414 Move branch-specific docs from GitHub Wiki into repo
Diffstat (limited to 'docs/exception_architecture.md')
-rw-r--r-- | docs/exception_architecture.md | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/docs/exception_architecture.md b/docs/exception_architecture.md new file mode 100644 index 00000000000..230a26e75c1 --- /dev/null +++ b/docs/exception_architecture.md @@ -0,0 +1,77 @@ +# 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 `verify` but only in debug mode. Do not use! + + +## 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::exception` + - `mongo::DBException` + - `mongo::AssertionException` + - `mongo::UserException` + - `mongo::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][1] heavily. + + +## Gotchas + +Gotchas to watch out for: + +- Generally, do not throw an `AssertionException` directly. Functions like `uasserted()` do work + beyond just that. In particular, it makes sure that the `getLastError` structures 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 `wassert` a 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). + + +[1]: https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization |