Merge "Merge branch release-4-6 into master"
[alexxy/gromacs.git] / src / gromacs / utility / exceptions.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
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.
8  *
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.
13  *
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.
18  *
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.
23  *
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.
31  *
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.
34  */
35 /*! \file
36  * \brief
37  * Declares common exception classes for fatal error handling.
38  *
39  * \author Teemu Murtola <teemu.murtola@gmail.com>
40  * \inpublicapi
41  * \ingroup module_utility
42  */
43 #ifndef GMX_UTILITY_EXCEPTIONS_H
44 #define GMX_UTILITY_EXCEPTIONS_H
45
46 #include <cstdio>
47 #include <cstdlib>
48
49 #include <exception>
50 #include <string>
51 #include <vector>
52
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>
59
60 namespace gmx
61 {
62
63 namespace internal
64 {
65 //! Internal container type for storing a list of nested exceptions.
66 typedef std::vector<boost::exception_ptr> NestedExceptionList;
67 }   // namespace internal
68
69 /*! \addtopublicapi
70  * \{
71  */
72
73 /*! \brief
74  * Provides information for Gromacs exception constructors.
75  *
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.
83  *
84  * \todo
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.
93  *
94  * \ingroup module_utility
95  */
96 class ExceptionInitializer
97 {
98     public:
99         /*! \brief
100          * Creates an initialized with the given string as the reason.
101          *
102          * \param[in] reason  Detailed reason for the exception.
103          * \throw     std::bad_alloc if out of memory.
104          *
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.
108          */
109         ExceptionInitializer(const char *reason)
110             : reason_(reason)
111         {
112         }
113         //! \copydoc ExceptionInitializer(const char *)
114         ExceptionInitializer(const std::string &reason)
115             : reason_(reason)
116         {
117         }
118
119         /*! \brief
120          * Returns true if addCurrentExceptionAsNested() has been called.
121          *
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.
125          */
126         bool hasNestedExceptions() const { return !nested_.empty(); }
127         /*! \brief
128          * Adds the currently caught exception as a nested exception.
129          *
130          * May be called multiple times; all provided exceptions will be added
131          * in a list of nested exceptions.
132          *
133          * Must not be called outside a catch block.
134          */
135         void addCurrentExceptionAsNested()
136         {
137             nested_.push_back(boost::current_exception());
138         }
139
140     private:
141         std::string                     reason_;
142         internal::NestedExceptionList   nested_;
143
144         friend class GromacsException;
145 };
146
147 /*! \brief
148  * Base class for all exception objects in Gromacs.
149  *
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.
159  *
160  * \ingroup module_utility
161  */
162 class GromacsException : public std::exception, public boost::exception
163 {
164     public:
165         /*! \brief
166          * Returns the reason string for the exception.
167          *
168          * The return value is the string that was passed to the constructor.
169          */
170         virtual const char *what() const throw();
171         /*! \brief
172          * Returns the error code corresponding to the exception type.
173          */
174         virtual int errorCode() const = 0;
175
176         /*! \brief
177          * Adds context information to this exception.
178          *
179          * \param[in] context  Context string to add.
180          * \throws    std::bad_alloc if out of memory.
181          *
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
184          * exception.
185          *
186          * \todo
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
191          * discussion.
192          */
193         void prependContext(const std::string &context);
194
195     protected:
196         /*! \brief
197          * Creates an exception object with the provided initializer/reason.
198          *
199          * \param[in] details  Initializer for the exception.
200          * \throws    std::bad_alloc if out of memory.
201          */
202         explicit GromacsException(const ExceptionInitializer &details);
203 };
204
205 /*! \brief
206  * Exception class for file I/O errors.
207  *
208  * \ingroup module_utility
209  */
210 class FileIOError : public GromacsException
211 {
212     public:
213         /*! \brief
214          * Creates an exception object with the provided initializer/reason.
215          *
216          * \param[in] details  Initializer for the exception.
217          * \throws    std::bad_alloc if out of memory.
218          *
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.
222          */
223         explicit FileIOError(const ExceptionInitializer &details)
224             : GromacsException(details) {}
225
226         virtual int errorCode() const;
227 };
228
229 /*! \brief
230  * Exception class for user input errors.
231  *
232  * Derived classes should be used to indicate the nature of the error instead
233  * of throwing this class directly.
234  *
235  * \ingroup module_utility
236  */
237 class UserInputError : public GromacsException
238 {
239     protected:
240         //! \copydoc FileIOError::FileIOError()
241         explicit UserInputError(const ExceptionInitializer &details)
242             : GromacsException(details) {}
243 };
244
245 /*! \brief
246  * Exception class for situations where user input cannot be parsed/understood.
247  *
248  * \ingroup module_utility
249  */
250 class InvalidInputError : public UserInputError
251 {
252     public:
253         //! \copydoc FileIOError::FileIOError()
254         explicit InvalidInputError(const ExceptionInitializer &details)
255             : UserInputError(details) {}
256
257         virtual int errorCode() const;
258 };
259
260 /*! \brief
261  * Exception class for situations where user input is inconsistent.
262  *
263  * \ingroup module_utility
264  */
265 class InconsistentInputError : public UserInputError
266 {
267     public:
268         //! \copydoc FileIOError::FileIOError()
269         explicit InconsistentInputError(const ExceptionInitializer &details)
270             : UserInputError(details) {}
271
272         virtual int errorCode() const;
273 };
274
275 /*! \brief
276  * Exception class for simulation instabilities.
277  *
278  * \ingroup module_utility
279  */
280 class SimulationInstabilityError : public GromacsException
281 {
282     public:
283         //! \copydoc FileIOError::FileIOError()
284         explicit SimulationInstabilityError(const ExceptionInitializer &details)
285             : GromacsException(details) {}
286
287         virtual int errorCode() const;
288 };
289
290 /*! \brief
291  * Exception class for internal errors.
292  *
293  * \ingroup module_utility
294  */
295 class InternalError : public GromacsException
296 {
297     public:
298         //! \copydoc FileIOError::FileIOError()
299         explicit InternalError(const ExceptionInitializer &details)
300             : GromacsException(details) {}
301
302         virtual int errorCode() const;
303 };
304
305 /*! \brief
306  * Exception class for incorrect use of an API.
307  *
308  * \ingroup module_utility
309  */
310 class APIError : public GromacsException
311 {
312     public:
313         //! \copydoc FileIOError::FileIOError()
314         explicit APIError(const ExceptionInitializer &details)
315             : GromacsException(details) {}
316
317         virtual int errorCode() const;
318 };
319
320 /*! \brief
321  * Exception class for use of an unimplemented feature.
322  *
323  * \ingroup module_utility
324  */
325 class NotImplementedError : public APIError
326 {
327     public:
328         //! \copydoc FileIOError::FileIOError()
329         explicit NotImplementedError(const ExceptionInitializer &details)
330             : APIError(details) {}
331
332         virtual int errorCode() const;
333 };
334
335
336 /*! \brief
337  * Macro for throwing an exception.
338  *
339  * \param[in] e    Exception object to throw.
340  *
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
344  * GromacsException.
345  *
346  * Basic usage:
347  * \code
348    if (value < 0)
349    {
350        GMX_THROW(InconsistentUserInput("Negative values not allowed for value"));
351    }
352  * \endcode
353  */
354 #define GMX_THROW(e) \
355     BOOST_THROW_EXCEPTION((e))
356
357 /*! \brief
358  * Macro for throwing an exception based on errno.
359  *
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.
363  *
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
370  * GromacsException.
371  *
372  * Typical usage (note that gmx::File wraps this particular case):
373  * \code
374    FILE *fp = fopen("filename.txt", "r");
375    if (fp == NULL)
376    {
377        GMX_THROW(FileIOError("Could not open file"), "fopen", errno);
378    }
379  * \endcode
380  */
381 #define GMX_THROW_WITH_ERRNO(e, syscall, err) \
382     do { \
383         int stored_errno_ = (err); \
384         GMX_THROW((e) << boost::errinfo_errno(stored_errno_) \
385                   << boost::errinfo_api_function(syscall)); \
386     } while (0)
387
388 /*! \brief
389  * Formats a standard fatal error message for reporting an exception.
390  *
391  * \param[in] fp  File to format the message to.
392  * \param[in] ex  Exception to format.
393  *
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.
396  *
397  * Normal usage in Gromacs command-line programs is like this:
398  * \code
399    int main(int argc, char *argv[])
400    {
401        gmx::init(&argc, &argv);
402        try
403        {
404            // The actual code for the program
405            return 0;
406        }
407        catch (const std::exception &ex)
408        {
409            gmx::printFatalErrorMessage(stderr, ex);
410            return gmx::processExceptionAtExit(ex);
411        }
412    }
413  * \endcode
414  */
415 void printFatalErrorMessage(FILE *fp, const std::exception &ex);
416 /*! \brief
417  * Formats an error message for reporting an exception.
418  *
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.
422  */
423 std::string formatExceptionMessageToString(const std::exception &ex);
424 /*! \brief
425  * Formats an error message for reporting an exception.
426  *
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.
430  */
431 void formatExceptionMessageToFile(FILE *fp, const std::exception &ex);
432 /*! \brief
433  * Handles an exception that is causing the program to terminate.
434  *
435  * \param[in] ex  Exception that is the cause for terminating the program.
436  * \returns   Return code to return from main().
437  *
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()).
442  *
443  * See printFatalErrorMessage() for example usage.
444  *
445  * Does not throw.
446  */
447 int processExceptionAtExit(const std::exception &ex);
448
449 /*! \brief
450  * Converts an exception into a return code.
451  */
452 int translateException(const std::exception &ex);
453
454 /*!\}*/
455
456 /*! \cond libapi */
457 /*! \libinternal \brief
458  * Macro for catching exceptions at C++ -> C boundary.
459  *
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.
465  *
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.
469  *
470  * Usage:
471  * \code
472    try
473    {
474        // C++ code
475    }
476    GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
477  * \endcode
478  *
479  * \inlibraryapi
480  */
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)); \
485     }
486 //! \endcond
487
488 } // namespace gmx
489
490 #endif