6 To make |Gromacs| behave like a proper library, we need to change the
7 way errors etc. are handled. Basically, the library should not print
8 out anything to stdio/stderr unless it is part of the API
9 specification, and even then, there should be a way for the user to
10 suppress the output. Also, the library should normally not terminate
11 the program without the user having control over this. There are
12 different types of errors, which also affects the handling. Different
13 cases are discussed separately below, split by the way they are
14 handled. These guidelines are starting to take their final form,
15 although details may still change.
17 * For programming errors, i.e., errors that should never occur if the
18 program is correctly written, it's acceptable to assert and
19 terminate the program. This applies to both errors in the library
20 and errors in user code or user input that calls the library.
21 Older code tends to still use ``assert()`` calls, but new
22 code should prefer more expressive functionality such as
23 ``GMX_RELEASE_ASSERT()``. This version of the macro will result
24 in asserts that are still present when the build type is Release,
25 which is what we want by default. In performance-sensitive parts
26 of the code, it is acceptable to rather use ``GMX_ASSERT()`` to
27 avoid the performance penalty of a branch when the code is compiled
28 for production use. By default, Jenkins builds the RelWithAssert
30 * For some errors it might be feasible to recover gracefully and
31 continue execution. In this case, your APIs should be defined
32 so that the API-user/programmer does not have to check separately
33 whether the problem was due to a programming error, but it's
34 better to e.g. use exceptions for recoverable errors and
35 asserts for programming errors.
36 * Exceptions should only be used for unexpected errors, e.g., out of
37 memory or file system IO errors. As a general guideline, incorrect
38 user input should not produce an untrapped exception resulting
39 in execution termination telling the user an exception occured.
40 Instead, you should catch exceptions in an earlier stack frame,
41 make a suitable decision about diagnostic messages, and then
42 decide how execution should be terminated.
43 * There is a global list of possible exceptions in
44 ``src/gromacs/utility/exceptions.h``, and the library should throw
45 one of these when it fails, possibly providing a more detailed
46 description of the reason for the failure. The types of exceptions
47 can be extended, and currently include:
49 - Out of memory (e.g. ``std::bad_alloc``)
51 - File I/O error (e.g. not found)
53 - Invalid user input (could not be understood)
55 - Inconsistent user input (parsed correctly, but has internal conflicts)
57 - Simulation instability
59 - Invalid API call/value/internal error (an assertion might also be used in such cases)
61 - In the internals of a module called from code that is not
62 exception safe, you can use exceptions for error handling, but
63 avoid propagating them to caller code.
65 * Avoid using exceptions to propagate errors across regions that start
66 or join threads with OpenMP, since OpenMP cannot make guarantees about
67 whether exceptions are caught or if the program will crash.
68 Currently we catch all exceptions before we leave an OpenMP threaded region.
69 If you throw an exception, make sure that it is caught and handled appropriately
70 in the same thread/OpenMP section.
71 * There are also cases where a library routine wants to report a
72 warning or a non-fatal error, but is still able to continue
73 processing. In this case you should try to collect all issues and
74 report and report them (similar to what grompp does with notes, warnings
75 and errors) instead of just returning the first error. It is irritating
76 to users if they fix the reported error, but then they keep getting
77 a new error message every time the rerun the program.
78 * A function should not fail as part of its normal operation.
79 However, doing nothing can be considered normal operation. A function
80 accessing data should typically also be callable when no such data is
81 available, but still return through normal means. If the failure is not
82 normal, it is OK to rather throw an exception.
84 For coding guidelines to make this all work, see :ref:`implementing exceptions`.