Merge release-4-6 into release-5-0
[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  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6  * and including many others, as listed in the AUTHORS file in the
7  * top-level source 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 and macros 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 //! \addtogroup module_utility
70 //! \{
71
72 /*! \brief
73  * Provides information for Gromacs exception constructors.
74  *
75  * This class exists to implement common functionality for initializing all
76  * Gromacs exceptions without having extra code in each exception class.
77  * In simple cases, it can be implicitly constructed by passing a simple string
78  * to an exception constructor.
79  * If more complex initialization is necessary, it is possible to explicitly
80  * construct an object of this type and then call other methods to add
81  * information before actually creating the exception object.
82  *
83  * \todo
84  * With the exception of the reason string, information added with this class
85  * is not currently accessible through any public API, except for calling
86  * printFatalErrorMessage(), formatExceptionMessageToString() or
87  * formatExceptionMessageToFile().  This is not implemented as there is not yet
88  * need for it, and it is not clear what would be the best alternative for the
89  * access.  It should be possible to refactor the internal implementation to
90  * suit the needs of such external access without requiring changes in code
91  * that throws these exceptions.
92  *
93  * \ingroup module_utility
94  */
95 class ExceptionInitializer
96 {
97     public:
98         /*! \brief
99          * Creates an initialized with the given string as the reason.
100          *
101          * \param[in] reason  Detailed reason for the exception.
102          * \throw     std::bad_alloc if out of memory.
103          *
104          * This constructor is not explicit to allow constructing exceptions
105          * with a plain string argument given to the constructor without adding
106          * extra code to each exception class.
107          */
108         ExceptionInitializer(const char *reason)
109             : reason_(reason)
110         {
111         }
112         //! \copydoc ExceptionInitializer(const char *)
113         ExceptionInitializer(const std::string &reason)
114             : reason_(reason)
115         {
116         }
117
118         /*! \brief
119          * Returns true if addCurrentExceptionAsNested() has been called.
120          *
121          * Provided for convenience for cases where exceptions will be added
122          * conditionally, and the caller wants to check whether any excetions
123          * were actually added.
124          */
125         bool hasNestedExceptions() const { return !nested_.empty(); }
126         /*! \brief
127          * Adds the currently caught exception as a nested exception.
128          *
129          * May be called multiple times; all provided exceptions will be added
130          * in a list of nested exceptions.
131          *
132          * Must not be called outside a catch block.
133          */
134         void addCurrentExceptionAsNested()
135         {
136             nested_.push_back(boost::current_exception());
137         }
138
139     private:
140         std::string                     reason_;
141         internal::NestedExceptionList   nested_;
142
143         friend class GromacsException;
144 };
145
146 /*! \brief
147  * Base class for all exception objects in Gromacs.
148  *
149  * Although boost recommends using virtual inheritance in exception hiearchies,
150  * it is not used here for two reasons:
151  * -# It is only useful when there is diamond inheritance, and that should
152  *    never occur in this exception hierarchy because this class is the only
153  *    instance of multiple inheritance (Gromacs programming guidelines prohibit
154  *    multiple inheritance from concrete classes, but it is unavoidable here
155  *    because of the design of boost::exception).
156  * -# Because the constructor takes an argument, virtual inheritance would
157  *    complicate any classes that inherit indirectly from this class.
158  *
159  * \inpublicapi
160  */
161 class GromacsException : public std::exception, public boost::exception
162 {
163     public:
164         /*! \brief
165          * Returns the reason string for the exception.
166          *
167          * The return value is the string that was passed to the constructor.
168          */
169         virtual const char *what() const throw();
170         /*! \brief
171          * Returns the error code corresponding to the exception type.
172          */
173         virtual int errorCode() const = 0;
174
175         /*! \brief
176          * Adds context information to this exception.
177          *
178          * \param[in] context  Context string to add.
179          * \throws    std::bad_alloc if out of memory.
180          *
181          * Typical use is to add additional information higher up in the call
182          * stack using this function in a catch block and the rethrow the
183          * exception.
184          *
185          * \todo
186          * The added information is currently not accessible through what(),
187          * nor through any other means except for calling
188          * printFatalErrorMessage(), formatExceptionMessageToString() or
189          * formatExceptionMessageToFile(). See ExceptionInitializer for more
190          * discussion.
191          */
192         void prependContext(const std::string &context);
193
194     protected:
195         /*! \brief
196          * Creates an exception object with the provided initializer/reason.
197          *
198          * \param[in] details  Initializer for the exception.
199          * \throws    std::bad_alloc if out of memory.
200          */
201         explicit GromacsException(const ExceptionInitializer &details);
202 };
203
204 /*! \brief
205  * Exception class for file I/O errors.
206  *
207  * \inpublicapi
208  */
209 class FileIOError : public GromacsException
210 {
211     public:
212         /*! \brief
213          * Creates an exception object with the provided initializer/reason.
214          *
215          * \param[in] details  Initializer for the exception.
216          * \throws    std::bad_alloc if out of memory.
217          *
218          * It is possible to call this constructor either with an explicit
219          * ExceptionInitializer object (useful for more complex cases), or
220          * a simple string if only a reason string needs to be provided.
221          */
222         explicit FileIOError(const ExceptionInitializer &details)
223             : GromacsException(details) {}
224
225         virtual int errorCode() const;
226 };
227
228 /*! \brief
229  * Exception class for user input errors.
230  *
231  * Derived classes should be used to indicate the nature of the error instead
232  * of throwing this class directly.
233  *
234  * \inpublicapi
235  */
236 class UserInputError : public GromacsException
237 {
238     protected:
239         //! \copydoc FileIOError::FileIOError()
240         explicit UserInputError(const ExceptionInitializer &details)
241             : GromacsException(details) {}
242 };
243
244 /*! \brief
245  * Exception class for situations where user input cannot be parsed/understood.
246  *
247  * \inpublicapi
248  */
249 class InvalidInputError : public UserInputError
250 {
251     public:
252         //! \copydoc FileIOError::FileIOError()
253         explicit InvalidInputError(const ExceptionInitializer &details)
254             : UserInputError(details) {}
255
256         virtual int errorCode() const;
257 };
258
259 /*! \brief
260  * Exception class for situations where user input is inconsistent.
261  *
262  * \inpublicapi
263  */
264 class InconsistentInputError : public UserInputError
265 {
266     public:
267         //! \copydoc FileIOError::FileIOError()
268         explicit InconsistentInputError(const ExceptionInitializer &details)
269             : UserInputError(details) {}
270
271         virtual int errorCode() const;
272 };
273
274 /*! \brief
275  * Exception class for simulation instabilities.
276  *
277  * \inpublicapi
278  */
279 class SimulationInstabilityError : public GromacsException
280 {
281     public:
282         //! \copydoc FileIOError::FileIOError()
283         explicit SimulationInstabilityError(const ExceptionInitializer &details)
284             : GromacsException(details) {}
285
286         virtual int errorCode() const;
287 };
288
289 /*! \brief
290  * Exception class for internal errors.
291  *
292  * \inpublicapi
293  */
294 class InternalError : public GromacsException
295 {
296     public:
297         //! \copydoc FileIOError::FileIOError()
298         explicit InternalError(const ExceptionInitializer &details)
299             : GromacsException(details) {}
300
301         virtual int errorCode() const;
302 };
303
304 /*! \brief
305  * Exception class for incorrect use of an API.
306  *
307  * \inpublicapi
308  */
309 class APIError : public GromacsException
310 {
311     public:
312         //! \copydoc FileIOError::FileIOError()
313         explicit APIError(const ExceptionInitializer &details)
314             : GromacsException(details) {}
315
316         virtual int errorCode() const;
317 };
318
319 /*! \brief
320  * Exception class for use of an unimplemented feature.
321  *
322  * \inpublicapi
323  */
324 class NotImplementedError : public APIError
325 {
326     public:
327         //! \copydoc FileIOError::FileIOError()
328         explicit NotImplementedError(const ExceptionInitializer &details)
329             : APIError(details) {}
330
331         virtual int errorCode() const;
332 };
333
334
335 /*! \brief
336  * Macro for throwing an exception.
337  *
338  * \param[in] e    Exception object to throw.
339  *
340  * Using this macro instead of \c throw directly makes it possible to uniformly
341  * attach information into the exception objects.
342  * \p e should evaluate to an instance of an object derived from
343  * GromacsException.
344  *
345  * Basic usage:
346  * \code
347    if (value < 0)
348    {
349        GMX_THROW(InconsistentUserInput("Negative values not allowed for value"));
350    }
351    \endcode
352  */
353 #define GMX_THROW(e) \
354     BOOST_THROW_EXCEPTION((e))
355
356 /*! \brief
357  * Macro for throwing an exception based on errno.
358  *
359  * \param[in] e       Exception object to throw.
360  * \param[in] syscall Name of the syscall that returned the error.
361  * \param[in] err     errno value returned by the syscall.
362  *
363  * This macro provides a convenience interface for throwing an exception to
364  * report an error based on a errno value.  In addition to adding the necessary
365  * information to the exception object, the macro also ensures that \p errno is
366  * evaluated before, e.g., the constructor of \p e may call other functions
367  * that could overwrite the errno value.
368  * \p e should evaluate to an instance of an object derived from
369  * GromacsException.
370  *
371  * Typical usage (note that gmx::File wraps this particular case):
372  * \code
373    FILE *fp = fopen("filename.txt", "r");
374    if (fp == NULL)
375    {
376        GMX_THROW(FileIOError("Could not open file"), "fopen", errno);
377    }
378    \endcode
379  */
380 #define GMX_THROW_WITH_ERRNO(e, syscall, err) \
381     do { \
382         int stored_errno_ = (err); \
383         GMX_THROW((e) << boost::errinfo_errno(stored_errno_) \
384                   << boost::errinfo_api_function(syscall)); \
385     } while (0)
386
387 /*! \brief
388  * Formats a standard fatal error message for reporting an exception.
389  *
390  * \param[in] fp  %File to format the message to.
391  * \param[in] ex  Exception to format.
392  *
393  * Does not throw.  If memory allocation fails or some other error occurs
394  * while formatting the error, tries to print a reasonable alternative message.
395  *
396  * Normal usage in Gromacs command-line programs is like this:
397  * \code
398    int main(int argc, char *argv[])
399    {
400        gmx::init(&argc, &argv);
401        try
402        {
403            // The actual code for the program
404            return 0;
405        }
406        catch (const std::exception &ex)
407        {
408            gmx::printFatalErrorMessage(stderr, ex);
409            return gmx::processExceptionAtExit(ex);
410        }
411    }
412    \endcode
413  */
414 void printFatalErrorMessage(FILE *fp, const std::exception &ex);
415 /*! \brief
416  * Formats an error message for reporting an exception.
417  *
418  * \param[in] ex  Exception to format.
419  * \returns   Formatted string containing details of \p ex.
420  * \throws    std::bad_alloc if out of memory.
421  */
422 std::string formatExceptionMessageToString(const std::exception &ex);
423 /*! \brief
424  * Formats an error message for reporting an exception.
425  *
426  * \param     fp  %File to write the message to.
427  * \param[in] ex  Exception to format.
428  * \throws    std::bad_alloc if out of memory.
429  */
430 void formatExceptionMessageToFile(FILE *fp, const std::exception &ex);
431 /*! \brief
432  * Handles an exception that is causing the program to terminate.
433  *
434  * \param[in] ex  Exception that is the cause for terminating the program.
435  * \returns   Return code to return from main().
436  *
437  * This method should be called as the last thing before terminating the
438  * program because of an exception.  It exists to terminate the program as
439  * gracefully as possible in the case of MPI processing (but the current
440  * implementation always calls MPI_Abort()).
441  *
442  * See printFatalErrorMessage() for example usage.
443  *
444  * Does not throw.
445  */
446 int processExceptionAtExit(const std::exception &ex);
447
448 /*! \brief
449  * Converts an exception into a return code.
450  */
451 int translateException(const std::exception &ex);
452
453 /*! \brief
454  * Macro for catching exceptions at C++ -> C boundary.
455  *
456  * This macro is intended for uniform handling of exceptions when C++ code is
457  * called from C code within Gromacs.  Since most existing code is written
458  * using the assumption that fatal errors terminate the program, this macro
459  * implements this behavior for exceptions.  It should only be used in cases
460  * where the error cannot be propagated upwards using return values or such.
461  *
462  * Having this as a macro instead of having the same code in each place makes
463  * it easy to 1) find all such locations in the code, and 2) change the exact
464  * behavior if needed.
465  *
466  * Usage:
467    \code
468    try
469    {
470        // C++ code
471    }
472    GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
473    \endcode
474  */
475 #define GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR \
476     catch (const std::exception &ex) { \
477         ::gmx::printFatalErrorMessage(stderr, ex); \
478         ::std::exit(::gmx::processExceptionAtExit(ex)); \
479     }
480
481 //! \}
482
483 } // namespace gmx
484
485 #endif