2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2011,2012,2013, by the GROMACS development team, led by
5 * David van der Spoel, Berk Hess, Erik Lindahl, and including many
6 * others, as listed in the AUTHORS file in the top-level source
7 * directory and at http://www.gromacs.org.
9 * GROMACS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * GROMACS is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with GROMACS; if not, see
21 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * If you want to redistribute modifications to GROMACS, please
25 * consider that scientific software is very special. Version
26 * control is crucial - bugs must be traceable. We will be happy to
27 * consider code for inclusion in the official distribution, but
28 * derived work must not be called official GROMACS. Details are found
29 * in the README & COPYING files - if they are missing, get the
30 * official version at http://www.gromacs.org.
32 * To help us fund GROMACS development, we humbly ask that you cite
33 * the research papers on the package. Check out http://www.gromacs.org.
37 * Declares common exception classes for fatal error handling.
39 * \author Teemu Murtola <teemu.murtola@gmail.com>
41 * \ingroup module_utility
43 #ifndef GMX_UTILITY_EXCEPTIONS_H
44 #define GMX_UTILITY_EXCEPTIONS_H
53 #include <boost/exception_ptr.hpp>
54 #include <boost/exception/errinfo_api_function.hpp>
55 #include <boost/exception/errinfo_errno.hpp>
56 #include <boost/exception/exception.hpp>
57 #include <boost/exception/info.hpp>
58 #include <boost/throw_exception.hpp>
65 //! Internal container type for storing a list of nested exceptions.
66 typedef std::vector<boost::exception_ptr> NestedExceptionList;
67 } // namespace internal
74 * Provides information for Gromacs exception constructors.
76 * This class exists to implement common functionality for initializing all
77 * Gromacs exceptions without having extra code in each exception class.
78 * In simple cases, it can be implicitly constructed by passing a simple string
79 * to an exception constructor.
80 * If more complex initialization is necessary, it is possible to explicitly
81 * construct an object of this type and then call other methods to add
82 * information before actually creating the exception object.
85 * With the exception of the reason string, information added with this class
86 * is not currently accessible through any public API, except for calling
87 * printFatalErrorMessage(), formatExceptionMessageToString() or
88 * formatExceptionMessageToFile(). This is not implemented as there is not yet
89 * need for it, and it is not clear what would be the best alternative for the
90 * access. It should be possible to refactor the internal implementation to
91 * suit the needs of such external access without requiring changes in code
92 * that throws these exceptions.
94 * \ingroup module_utility
96 class ExceptionInitializer
100 * Creates an initialized with the given string as the reason.
102 * \param[in] reason Detailed reason for the exception.
103 * \throw std::bad_alloc if out of memory.
105 * This constructor is not explicit to allow constructing exceptions
106 * with a plain string argument given to the constructor without adding
107 * extra code to each exception class.
109 ExceptionInitializer(const char *reason)
113 //! \copydoc ExceptionInitializer(const char *)
114 ExceptionInitializer(const std::string &reason)
120 * Returns true if addCurrentExceptionAsNested() has been called.
122 * Provided for convenience for cases where exceptions will be added
123 * conditionally, and the caller wants to check whether any excetions
124 * were actually added.
126 bool hasNestedExceptions() const { return !nested_.empty(); }
128 * Adds the currently caught exception as a nested exception.
130 * May be called multiple times; all provided exceptions will be added
131 * in a list of nested exceptions.
133 * Must not be called outside a catch block.
135 void addCurrentExceptionAsNested()
137 nested_.push_back(boost::current_exception());
142 internal::NestedExceptionList nested_;
144 friend class GromacsException;
148 * Base class for all exception objects in Gromacs.
150 * Although boost recommends using virtual inheritance in exception hiearchies,
151 * it is not used here for two reasons:
152 * -# It is only useful when there is diamond inheritance, and that should
153 * never occur in this exception hierarchy because this class is the only
154 * instance of multiple inheritance (Gromacs programming guidelines prohibit
155 * multiple inheritance from concrete classes, but it is unavoidable here
156 * because of the design of boost::exception).
157 * -# Because the constructor takes an argument, virtual inheritance would
158 * complicate any classes that inherit indirectly from this class.
160 * \ingroup module_utility
162 class GromacsException : public std::exception, public boost::exception
166 * Returns the reason string for the exception.
168 * The return value is the string that was passed to the constructor.
170 virtual const char *what() const throw();
172 * Returns the error code corresponding to the exception type.
174 virtual int errorCode() const = 0;
177 * Adds context information to this exception.
179 * \param[in] context Context string to add.
180 * \throws std::bad_alloc if out of memory.
182 * Typical use is to add additional information higher up in the call
183 * stack using this function in a catch block and the rethrow the
187 * The added information is currently not accessible through what(),
188 * nor through any other means except for calling
189 * printFatalErrorMessage(), formatExceptionMessageToString() or
190 * formatExceptionMessageToFile(). See ExceptionInitializer for more
193 void prependContext(const std::string &context);
197 * Creates an exception object with the provided initializer/reason.
199 * \param[in] details Initializer for the exception.
200 * \throws std::bad_alloc if out of memory.
202 explicit GromacsException(const ExceptionInitializer &details);
206 * Exception class for file I/O errors.
208 * \ingroup module_utility
210 class FileIOError : public GromacsException
214 * Creates an exception object with the provided initializer/reason.
216 * \param[in] details Initializer for the exception.
217 * \throws std::bad_alloc if out of memory.
219 * It is possible to call this constructor either with an explicit
220 * ExceptionInitializer object (useful for more complex cases), or
221 * a simple string if only a reason string needs to be provided.
223 explicit FileIOError(const ExceptionInitializer &details)
224 : GromacsException(details) {}
226 virtual int errorCode() const;
230 * Exception class for user input errors.
232 * Derived classes should be used to indicate the nature of the error instead
233 * of throwing this class directly.
235 * \ingroup module_utility
237 class UserInputError : public GromacsException
240 //! \copydoc FileIOError::FileIOError()
241 explicit UserInputError(const ExceptionInitializer &details)
242 : GromacsException(details) {}
246 * Exception class for situations where user input cannot be parsed/understood.
248 * \ingroup module_utility
250 class InvalidInputError : public UserInputError
253 //! \copydoc FileIOError::FileIOError()
254 explicit InvalidInputError(const ExceptionInitializer &details)
255 : UserInputError(details) {}
257 virtual int errorCode() const;
261 * Exception class for situations where user input is inconsistent.
263 * \ingroup module_utility
265 class InconsistentInputError : public UserInputError
268 //! \copydoc FileIOError::FileIOError()
269 explicit InconsistentInputError(const ExceptionInitializer &details)
270 : UserInputError(details) {}
272 virtual int errorCode() const;
276 * Exception class for simulation instabilities.
278 * \ingroup module_utility
280 class SimulationInstabilityError : public GromacsException
283 //! \copydoc FileIOError::FileIOError()
284 explicit SimulationInstabilityError(const ExceptionInitializer &details)
285 : GromacsException(details) {}
287 virtual int errorCode() const;
291 * Exception class for internal errors.
293 * \ingroup module_utility
295 class InternalError : public GromacsException
298 //! \copydoc FileIOError::FileIOError()
299 explicit InternalError(const ExceptionInitializer &details)
300 : GromacsException(details) {}
302 virtual int errorCode() const;
306 * Exception class for incorrect use of an API.
308 * \ingroup module_utility
310 class APIError : public GromacsException
313 //! \copydoc FileIOError::FileIOError()
314 explicit APIError(const ExceptionInitializer &details)
315 : GromacsException(details) {}
317 virtual int errorCode() const;
321 * Exception class for use of an unimplemented feature.
323 * \ingroup module_utility
325 class NotImplementedError : public APIError
328 //! \copydoc FileIOError::FileIOError()
329 explicit NotImplementedError(const ExceptionInitializer &details)
330 : APIError(details) {}
332 virtual int errorCode() const;
337 * Macro for throwing an exception.
339 * \param[in] e Exception object to throw.
341 * Using this macro instead of \c throw directly makes it possible to uniformly
342 * attach information into the exception objects.
343 * \p e should evaluate to an instance of an object derived from
350 GMX_THROW(InconsistentUserInput("Negative values not allowed for value"));
354 #define GMX_THROW(e) \
355 BOOST_THROW_EXCEPTION((e))
358 * Macro for throwing an exception based on errno.
360 * \param[in] e Exception object to throw.
361 * \param[in] syscall Name of the syscall that returned the error.
362 * \param[in] err errno value returned by the syscall.
364 * This macro provides a convenience interface for throwing an exception to
365 * report an error based on a errno value. In addition to adding the necessary
366 * information to the exception object, the macro also ensures that \p errno is
367 * evaluated before, e.g., the constructor of \p e may call other functions
368 * that could overwrite the errno value.
369 * \p e should evaluate to an instance of an object derived from
372 * Typical usage (note that gmx::File wraps this particular case):
374 FILE *fp = fopen("filename.txt", "r");
377 GMX_THROW(FileIOError("Could not open file"), "fopen", errno);
381 #define GMX_THROW_WITH_ERRNO(e, syscall, err) \
383 int stored_errno_ = (err); \
384 GMX_THROW((e) << boost::errinfo_errno(stored_errno_) \
385 << boost::errinfo_api_function(syscall)); \
389 * Formats a standard fatal error message for reporting an exception.
391 * \param[in] fp File to format the message to.
392 * \param[in] ex Exception to format.
394 * Does not throw. If memory allocation fails or some other error occurs
395 * while formatting the error, tries to print a reasonable alternative message.
397 * Normal usage in Gromacs command-line programs is like this:
399 int main(int argc, char *argv[])
401 gmx::init(&argc, &argv);
404 // The actual code for the program
407 catch (const std::exception &ex)
409 gmx::printFatalErrorMessage(stderr, ex);
410 return gmx::processExceptionAtExit(ex);
415 void printFatalErrorMessage(FILE *fp, const std::exception &ex);
417 * Formats an error message for reporting an exception.
419 * \param[in] ex Exception to format.
420 * \returns Formatted string containing details of \p ex.
421 * \throws std::bad_alloc if out of memory.
423 std::string formatExceptionMessageToString(const std::exception &ex);
425 * Formats an error message for reporting an exception.
427 * \param fp File to write the message to.
428 * \param[in] ex Exception to format.
429 * \throws std::bad_alloc if out of memory.
431 void formatExceptionMessageToFile(FILE *fp, const std::exception &ex);
433 * Handles an exception that is causing the program to terminate.
435 * \param[in] ex Exception that is the cause for terminating the program.
436 * \returns Return code to return from main().
438 * This method should be called as the last thing before terminating the
439 * program because of an exception. It exists to terminate the program as
440 * gracefully as possible in the case of MPI processing (but the current
441 * implementation always calls MPI_Abort()).
443 * See printFatalErrorMessage() for example usage.
447 int processExceptionAtExit(const std::exception &ex);
450 * Converts an exception into a return code.
452 int translateException(const std::exception &ex);
457 /*! \libinternal \brief
458 * Macro for catching exceptions at C++ -> C boundary.
460 * This macro is intended for uniform handling of exceptions when C++ code is
461 * called from C code within Gromacs. Since most existing code is written
462 * using the assumption that fatal errors terminate the program, this macro
463 * implements this behavior for exceptions. It should only be used in cases
464 * where the error cannot be propagated upwards using return values or such.
466 * Having this as a macro instead of having the same code in each place makes
467 * it easy to 1) find all such locations in the code, and 2) change the exact
468 * behavior if needed.
476 GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
481 #define GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR \
482 catch (const std::exception &ex) { \
483 ::gmx::printFatalErrorMessage(stderr, ex); \
484 ::std::exit(::gmx::processExceptionAtExit(ex)); \