9ba4cd6e4ea1a08f674175a7148edda145a70038
[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,2014,2015,2016,2018, 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  * The basic approach is the same as in boost::exception for storing additional
40  * context information to exceptions, but since that functionality is a very
41  * small and simple part of boost::exception, the code is duplicated here.
42  *
43  * \author Teemu Murtola <teemu.murtola@gmail.com>
44  * \inpublicapi
45  * \ingroup module_utility
46  */
47 #ifndef GMX_UTILITY_EXCEPTIONS_H
48 #define GMX_UTILITY_EXCEPTIONS_H
49
50 #include <cstdio>
51 #include <cstdlib>
52
53 #include <exception>
54 #include <memory>
55 #include <string>
56 #include <type_traits>
57 #include <typeindex>
58 #include <vector>
59
60 #include "gromacs/utility/basedefinitions.h"
61 #include "gromacs/utility/classhelpers.h"
62 #include "gromacs/utility/current_function.h"
63 #include "gromacs/utility/gmxassert.h"
64
65 namespace gmx
66 {
67
68 class TextWriter;
69
70 namespace internal
71 {
72 //! Internal container type for storing a list of nested exceptions.
73 typedef std::vector<std::exception_ptr> NestedExceptionList;
74
75 /*! \internal
76  * \brief
77  * Base class for ExceptionInfo.
78  *
79  * This class only provides a way to store different ExceptionInfo objects in
80  * the same container.  Actual access to the ExceptionInfo items is handled by
81  * downcasting, after looking up the correct item based on its type.
82  *
83  * \ingroup module_utility
84  */
85 class IExceptionInfo
86 {
87     public:
88         virtual ~IExceptionInfo();
89         GMX_DEFAULT_CONSTRUCTORS(IExceptionInfo);
90 };
91
92 //! Smart pointer to manage IExceptionInfo ownership.
93 typedef std::unique_ptr<IExceptionInfo> ExceptionInfoPointer;
94
95 class ExceptionData;
96
97 }   // namespace internal
98
99 //! \addtogroup module_utility
100 //! \{
101
102 /*! \brief
103  * Stores additional context information for exceptions.
104  *
105  * \tparam  Tag  Tag type (typically, a forward-declared struct that is not
106  *     defined anywhere) that makes all ExceptionInfo types unique, even if
107  *     they have the same value type.
108  * \tparam  T    Type of value this object stores.
109  *     Needs to be copy-constructible.
110  *
111  * Example of declaring a new info type that stores an integer:
112  * \code
113    typedef ExceptionInfo<struct ExceptionInfoMyInfo_, int> ExceptionInfoMyInfo;
114    \endcode
115  *
116  * \inpublicapi
117  */
118 template <class Tag, typename T>
119 class ExceptionInfo : public internal::IExceptionInfo
120 {
121     public:
122         //! The type of value stored in this object.
123         typedef T value_type;
124
125         //! Creates an info object from given value.
126         explicit ExceptionInfo(const T &value)
127             : value_(value)
128         {
129         }
130
131         //! Returns the stored value.
132         const T &value() const { return value_; }
133
134     private:
135         T       value_;
136 };
137
138 /*! \internal
139  * \brief
140  * Stores the location from which an exception was thrown.
141  */
142 struct ThrowLocation
143 {
144     //! Creates an object for storing the throw location.
145     ThrowLocation(const char *func, const char *file, int line)
146         : func(func), file(file), line(line)
147     {
148     }
149
150     //! Function where the throw occurred.
151     const char *func;
152     //! File where the throw occurred.
153     const char *file;
154     //! Line number where the throw occurred.
155     int         line;
156 };
157
158 //! Stores `errno` value that triggered the exception.
159 typedef ExceptionInfo<struct ExceptionInfoErrno_, int>
160     ExceptionInfoErrno;
161 //! Stores the function name that returned the `errno` in ExceptionInfoErrno.
162 typedef ExceptionInfo<struct ExceptionInfoApiFunc_, const char *>
163     ExceptionInfoApiFunction;
164 //! Stores the location where the exception was thrown.
165 typedef ExceptionInfo<struct ExceptionInfoLocation_, ThrowLocation>
166     ExceptionInfoLocation;
167
168 /*! \brief
169  * Provides information for Gromacs exception constructors.
170  *
171  * This class exists to implement common functionality for initializing all
172  * Gromacs exceptions without having extra code in each exception class.
173  * In simple cases, it can be implicitly constructed by passing a simple string
174  * to an exception constructor.
175  * If more complex initialization is necessary, it is possible to explicitly
176  * construct an object of this type and then call other methods to add
177  * information before actually creating the exception object.
178  *
179  * \todo
180  * With the exception of the reason string, information added with this class
181  * is not currently accessible through any public API, except for calling
182  * printFatalErrorMessage(), formatExceptionMessageToString() or
183  * formatExceptionMessageToFile().  This is not implemented as there is not yet
184  * need for it, and it is not clear what would be the best alternative for the
185  * access.  It should be possible to refactor the internal implementation to
186  * suit the needs of such external access without requiring changes in code
187  * that throws these exceptions.
188  *
189  * \ingroup module_utility
190  */
191 class ExceptionInitializer
192 {
193     public:
194         /*! \brief
195          * Creates an initialized with the given string as the reason.
196          *
197          * \param[in] reason  Detailed reason for the exception.
198          * \throw     std::bad_alloc if out of memory.
199          *
200          * This constructor is not explicit to allow constructing exceptions
201          * with a plain string argument given to the constructor without adding
202          * extra code to each exception class.
203          */
204         ExceptionInitializer(const char *reason)
205             : reason_(reason)
206         {
207         }
208         //! \copydoc ExceptionInitializer(const char *)
209         ExceptionInitializer(const std::string &reason)
210             : reason_(reason)
211         {
212         }
213
214         /*! \brief
215          * Returns true if addCurrentExceptionAsNested() has been called.
216          *
217          * Provided for convenience for cases where exceptions will be added
218          * conditionally, and the caller wants to check whether any excetions
219          * were actually added.
220          */
221         bool hasNestedExceptions() const { return !nested_.empty(); }
222         /*! \brief
223          * Adds the currently caught exception as a nested exception.
224          *
225          * May be called multiple times; all provided exceptions will be added
226          * in a list of nested exceptions.
227          *
228          * Must not be called outside a catch block.
229          */
230         void addCurrentExceptionAsNested()
231         {
232             nested_.push_back(std::current_exception());
233         }
234         /*! \brief
235          * Adds the specified exception as a nested exception.
236          *
237          * May be called multiple times; all provided exceptions will be added
238          * in a list of nested exceptions.
239          *
240          * This is equivalent to throwing \p ex and calling
241          * addCurrentExceptionAsNested() in the catch block, but potentially
242          * more efficient.
243          */
244         template <class Exception>
245         void addNested(const Exception &ex)
246         {
247             nested_.push_back(std::make_exception_ptr(ex));
248         }
249
250     private:
251         std::string                     reason_;
252         internal::NestedExceptionList   nested_;
253
254         friend class GromacsException;
255 };
256
257 /*! \brief
258  * Base class for all exception objects in Gromacs.
259  *
260  * \inpublicapi
261  */
262 class GromacsException : public std::exception
263 {
264     public:
265         // Explicitly declared because some compiler/library combinations warn
266         // about missing noexcept otherwise.
267         virtual ~GromacsException() noexcept {}
268
269         GMX_DEFAULT_CONSTRUCTORS(GromacsException);
270
271         /*! \brief
272          * Returns the reason string for the exception.
273          *
274          * The return value is the string that was passed to the constructor.
275          */
276         virtual const char *what() const noexcept;
277         /*! \brief
278          * Returns the error code corresponding to the exception type.
279          */
280         virtual int errorCode() const = 0;
281
282         /*! \brief
283          * Returns the value associated with given ExceptionInfo.
284          *
285          * \tparam  InfoType  ExceptionInfo type to get the value for.
286          * \returns Value set for `InfoType`, or `nullptr` if such info has not
287          *     been set.
288          *
289          * Does not throw.
290          */
291         template <class InfoType>
292         const typename InfoType::value_type *getInfo() const
293         {
294             const internal::IExceptionInfo *item = getInfo(typeid(InfoType));
295             if (item != nullptr)
296             {
297                 GMX_ASSERT(dynamic_cast<const InfoType *>(item) != nullptr,
298                            "Invalid exception info item found");
299                 return &static_cast<const InfoType *>(item)->value();
300             }
301             return nullptr;
302         }
303
304         /*! \brief
305          * Associates extra information with the exception.
306          *
307          * \tparam  Tag  ExceptionInfo tag type.
308          * \tparam  T          ExceptionInfo value type.
309          * \param[in] item  ExceptionInfo to associate.
310          * \throws std::bad_alloc if out of memory.
311          * \throws unspecified    any exception thrown by `T` copy construction.
312          *
313          * If an item of this type is already associated, it is overwritten.
314          */
315         template <class Tag, typename T>
316         void setInfo(const ExceptionInfo<Tag, T> &item)
317         {
318             typedef ExceptionInfo<Tag, T> ItemType;
319             internal::ExceptionInfoPointer itemPtr(new ItemType(item));
320             setInfo(typeid(ItemType), std::move(itemPtr));
321         }
322
323         /*! \brief
324          * Adds context information to this exception.
325          *
326          * \param[in] context  Context string to add.
327          * \throws    std::bad_alloc if out of memory.
328          *
329          * Typical use is to add additional information higher up in the call
330          * stack using this function in a catch block and the rethrow the
331          * exception.
332          *
333          * \todo
334          * The added information is currently not accessible through what(),
335          * nor through any other means except for calling
336          * printFatalErrorMessage(), formatExceptionMessageToString() or
337          * formatExceptionMessageToFile(). See ExceptionInitializer for more
338          * discussion.
339          */
340         void prependContext(const std::string &context);
341
342     protected:
343         /*! \brief
344          * Creates an exception object with the provided initializer/reason.
345          *
346          * \param[in] details  Initializer for the exception.
347          * \throws    std::bad_alloc if out of memory.
348          */
349         explicit GromacsException(const ExceptionInitializer &details);
350
351     private:
352         const internal::IExceptionInfo *getInfo(const std::type_index &index) const;
353         void setInfo(const std::type_index &index, internal::ExceptionInfoPointer &&item);
354
355         std::shared_ptr<internal::ExceptionData> data_;
356 };
357
358 /*! \brief
359  * Associates extra information with an exception.
360  *
361  * \tparam  Exception  Exception type (must be derived from GromacsException).
362  * \tparam  Tag        ExceptionInfo tag.
363  * \tparam  T          ExceptionInfo value type.
364  * \param[in,out] ex   Exception to associate the information to.
365  * \param[in]     item Information to associate.
366  *
367  * \internal
368  * The association is done with a templated non-member operator of exactly this
369  * form to make the simple syntax of GMX_THROW() possible.  To support this,
370  * this operation needs to:
371  *  - Allow setting information in a temporary to support
372  *    `GMX_THROW(InvalidInputError(ex))`.
373  *  - Return a copy of the same class it takes in.  The compiler needs
374  *    this information to throw the correct type of exception.  This
375  *    would be tedious to achieve with a member function (without a
376  *    lot of code duplication).  Generally, \c ex will be a temporary,
377  *    copied twice and returned by value, which the compiler will
378  *    typically elide away (and anyway performance is not important
379  *    when throwing).  We are not using the typical
380  *    return-by-const-reference idiom for this operator so that
381  *    tooling can reliably see that we are throwing by value.
382  *  - Provide convenient syntax for adding multiple items.  A non-member
383  *    function that would require nested calls would look ugly for such cases.
384  *
385  * The reason for the enable_if is that this way, it does not conflict with
386  * other overloads of `operator<<` for ExceptionInfo objects, in case someone
387  * would like to declare those.  But currently we do not have such overloads, so
388  * if the enable_if causes problems with some compilers, it can be removed.
389  */
390 template <class Exception, class Tag, class T>
391 inline
392 typename std::enable_if<std::is_base_of<GromacsException, Exception>::value, Exception>::type
393 operator<<(Exception ex, const ExceptionInfo<Tag, T> &item)
394 {
395     ex.setInfo(item);
396     return ex;
397 }
398
399 /*! \brief
400  * Exception class for file I/O errors.
401  *
402  * \inpublicapi
403  */
404 class FileIOError : public GromacsException
405 {
406     public:
407         /*! \brief
408          * Creates an exception object with the provided initializer/reason.
409          *
410          * \param[in] details  Initializer for the exception.
411          * \throws    std::bad_alloc if out of memory.
412          *
413          * It is possible to call this constructor either with an explicit
414          * ExceptionInitializer object (useful for more complex cases), or
415          * a simple string if only a reason string needs to be provided.
416          */
417         explicit FileIOError(const ExceptionInitializer &details)
418             : GromacsException(details) {}
419
420         virtual int errorCode() const;
421 };
422
423 /*! \brief
424  * Exception class for user input errors.
425  *
426  * Derived classes should be used to indicate the nature of the error instead
427  * of throwing this class directly.
428  *
429  * \inpublicapi
430  */
431 class UserInputError : public GromacsException
432 {
433     protected:
434         //! \copydoc FileIOError::FileIOError()
435         explicit UserInputError(const ExceptionInitializer &details)
436             : GromacsException(details) {}
437 };
438
439 /*! \brief
440  * Exception class for situations where user input cannot be parsed/understood.
441  *
442  * \inpublicapi
443  */
444 class InvalidInputError : public UserInputError
445 {
446     public:
447         //! \copydoc FileIOError::FileIOError()
448         explicit InvalidInputError(const ExceptionInitializer &details)
449             : UserInputError(details) {}
450
451         virtual int errorCode() const;
452 };
453
454 /*! \brief
455  * Exception class for situations where user input is inconsistent.
456  *
457  * \inpublicapi
458  */
459 class InconsistentInputError : public UserInputError
460 {
461     public:
462         //! \copydoc FileIOError::FileIOError()
463         explicit InconsistentInputError(const ExceptionInitializer &details)
464             : UserInputError(details) {}
465
466         virtual int errorCode() const;
467 };
468
469 /*! \brief
470  * Exception class when a specified tolerance cannot be achieved.
471  *
472  * \inpublicapi
473  */
474 class ToleranceError : public GromacsException
475 {
476     public:
477         /*! \brief
478          * Creates an exception object with the provided initializer/reason.
479          *
480          * \param[in] details  Initializer for the exception.
481          * \throws    std::bad_alloc if out of memory.
482          *
483          * It is possible to call this constructor either with an explicit
484          * ExceptionInitializer object (useful for more complex cases), or
485          * a simple string if only a reason string needs to be provided.
486          */
487         explicit ToleranceError(const ExceptionInitializer &details)
488             : GromacsException(details) {}
489
490         virtual int errorCode() const;
491 };
492
493 /*! \brief
494  * Exception class for simulation instabilities.
495  *
496  * \inpublicapi
497  */
498 class SimulationInstabilityError : public GromacsException
499 {
500     public:
501         //! \copydoc FileIOError::FileIOError()
502         explicit SimulationInstabilityError(const ExceptionInitializer &details)
503             : GromacsException(details) {}
504
505         virtual int errorCode() const;
506 };
507
508 /*! \brief
509  * Exception class for internal errors.
510  *
511  * \inpublicapi
512  */
513 class InternalError : public GromacsException
514 {
515     public:
516         //! \copydoc FileIOError::FileIOError()
517         explicit InternalError(const ExceptionInitializer &details)
518             : GromacsException(details) {}
519
520         virtual int errorCode() const;
521 };
522
523 /*! \brief
524  * Exception class for incorrect use of an API.
525  *
526  * \inpublicapi
527  */
528 class APIError : public GromacsException
529 {
530     public:
531         //! \copydoc FileIOError::FileIOError()
532         explicit APIError(const ExceptionInitializer &details)
533             : GromacsException(details) {}
534
535         virtual int errorCode() const;
536 };
537
538 /*! \brief
539  * Exception class for out-of-range values or indices
540  *
541  * \inpublicapi
542  */
543 class RangeError : public GromacsException
544 {
545     public:
546         //! \copydoc FileIOError::FileIOError()
547         explicit RangeError(const ExceptionInitializer &details)
548             : GromacsException(details) {}
549
550         virtual int errorCode() const;
551 };
552
553 /*! \brief
554  * Exception class for use of an unimplemented feature.
555  *
556  * \inpublicapi
557  */
558 class NotImplementedError : public APIError
559 {
560     public:
561         //! \copydoc FileIOError::FileIOError()
562         explicit NotImplementedError(const ExceptionInitializer &details)
563             : APIError(details) {}
564
565         virtual int errorCode() const;
566 };
567
568 /*! \brief
569  * Macro for throwing an exception.
570  *
571  * \param[in] e    Exception object to throw.
572  *
573  * Using this macro instead of \c throw directly makes it possible to uniformly
574  * attach information into the exception objects.
575  * \p e should evaluate to an instance of an object derived from
576  * GromacsException.
577  *
578  * Basic usage:
579  * \code
580    if (value < 0)
581    {
582        GMX_THROW(InconsistentUserInput("Negative values not allowed for value"));
583    }
584    \endcode
585  */
586 #define GMX_THROW(e) \
587     throw (e) << gmx::ExceptionInfoLocation(gmx::ThrowLocation(GMX_CURRENT_FUNCTION, __FILE__, __LINE__))
588
589 /*! \brief
590  * Macro for throwing an exception based on errno.
591  *
592  * \param[in] e       Exception object to throw.
593  * \param[in] syscall Name of the syscall that returned the error.
594  * \param[in] err     errno value returned by the syscall.
595  *
596  * This macro provides a convenience interface for throwing an exception to
597  * report an error based on a errno value.  In addition to adding the necessary
598  * information to the exception object, the macro also ensures that \p errno is
599  * evaluated before, e.g., the constructor of \p e may call other functions
600  * that could overwrite the errno value.
601  * \p e should evaluate to an instance of an object derived from
602  * GromacsException.
603  *
604  * Typical usage (note that gmx::File wraps this particular case):
605  * \code
606    FILE *fp = fopen("filename.txt", "r");
607    if (fp == NULL)
608    {
609        GMX_THROW(FileIOError("Could not open file"), "fopen", errno);
610    }
611    \endcode
612  */
613 #define GMX_THROW_WITH_ERRNO(e, syscall, err) \
614     do { \
615         int stored_errno_ = (err); \
616         GMX_THROW((e) << gmx::ExceptionInfoErrno(stored_errno_) \
617                   << gmx::ExceptionInfoApiFunction(syscall)); \
618     } while (0)
619 //TODO: Add an equivalent macro for Windows GetLastError
620
621 /*! \brief
622  * Formats a standard fatal error message for reporting an exception.
623  *
624  * \param[in] fp  %File to format the message to.
625  * \param[in] ex  Exception to format.
626  *
627  * Does not throw.  If memory allocation fails or some other error occurs
628  * while formatting the error, tries to print a reasonable alternative message.
629  *
630  * Normal usage in Gromacs command-line programs is like this:
631  * \code
632    int main(int argc, char *argv[])
633    {
634        gmx::init(&argc, &argv);
635        try
636        {
637            // The actual code for the program
638            return 0;
639        }
640        catch (const std::exception &ex)
641        {
642            gmx::printFatalErrorMessage(stderr, ex);
643            return gmx::processExceptionAtExit(ex);
644        }
645    }
646    \endcode
647  */
648 void printFatalErrorMessage(FILE *fp, const std::exception &ex);
649 /*! \brief
650  * Formats an error message for reporting an exception.
651  *
652  * \param[in] ex  Exception to format.
653  * \returns   Formatted string containing details of \p ex.
654  * \throws    std::bad_alloc if out of memory.
655  */
656 std::string formatExceptionMessageToString(const std::exception &ex);
657 /*! \brief
658  * Formats an error message for reporting an exception.
659  *
660  * \param     fp  %File to write the message to.
661  * \param[in] ex  Exception to format.
662  * \throws    std::bad_alloc if out of memory.
663  */
664 void formatExceptionMessageToFile(FILE *fp, const std::exception &ex);
665 /*! \brief
666  * Formats an error message for reporting an exception.
667  *
668  * \param     writer  Writer to use for writing the message.
669  * \param[in] ex      Exception to format.
670  * \throws    std::bad_alloc if out of memory.
671  */
672 void formatExceptionMessageToWriter(TextWriter           *writer,
673                                     const std::exception &ex);
674 /*! \brief
675  * Handles an exception that is causing the program to terminate.
676  *
677  * \param[in] ex  Exception that is the cause for terminating the program.
678  * \returns   Return code to return from main().
679  *
680  * This method should be called as the last thing before terminating the
681  * program because of an exception.  It exists to terminate the program as
682  * gracefully as possible in the case of MPI processing (but the current
683  * implementation always calls MPI_Abort()).
684  *
685  * See printFatalErrorMessage() for example usage.
686  *
687  * Does not throw.
688  */
689 int processExceptionAtExit(const std::exception &ex);
690
691 /*! \brief
692  * Helper function for terminating the program on an exception.
693  *
694  * \param[in] ex  Exception that is the cause for terminating the program.
695  *
696  * Does not throw, and does not return.
697  */
698 [[noreturn]] void processExceptionAsFatalError(const std::exception &ex);
699
700 /*! \brief
701  * Macro for catching exceptions at C++ -> C boundary.
702  *
703  * This macro is intended for uniform handling of exceptions when C++ code is
704  * called from C code within Gromacs.  Since most existing code is written
705  * using the assumption that fatal errors terminate the program, this macro
706  * implements this behavior for exceptions.  It should only be used in cases
707  * where the error cannot be propagated upwards using return values or such.
708  *
709  * Having this as a macro instead of having the same code in each place makes
710  * it easy to 1) find all such locations in the code, and 2) change the exact
711  * behavior if needed.
712  *
713  * Usage:
714    \code
715    try
716    {
717        // C++ code
718    }
719    GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
720    \endcode
721  */
722 #define GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR \
723     catch (const std::exception &ex) { \
724         ::gmx::processExceptionAsFatalError(ex); \
725     }
726
727 //! \}
728
729 } // namespace gmx
730
731 #endif