1 /* 2 * This file is part of the GROMACS molecular simulation package. 3 * 4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands. 5 * Copyright (c) 2001-2004, The GROMACS development team. 6 * Copyright (c) 2012,2014,2015,2018,2019, by the GROMACS development team, led by 7 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl, 8 * and including many others, as listed in the AUTHORS file in the 9 * top-level source directory and at http://www.gromacs.org. 10 * 11 * GROMACS is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU Lesser General Public License 13 * as published by the Free Software Foundation; either version 2.1 14 * of the License, or (at your option) any later version. 15 * 16 * GROMACS is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 * Lesser General Public License for more details. 20 * 21 * You should have received a copy of the GNU Lesser General Public 22 * License along with GROMACS; if not, see 23 * http://www.gnu.org/licenses, or write to the Free Software Foundation, 24 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 25 * 26 * If you want to redistribute modifications to GROMACS, please 27 * consider that scientific software is very special. Version 28 * control is crucial - bugs must be traceable. We will be happy to 29 * consider code for inclusion in the official distribution, but 30 * derived work must not be called official GROMACS. Details are found 31 * in the README & COPYING files - if they are missing, get the 32 * official version at http://www.gromacs.org. 33 * 34 * To help us fund GROMACS development, we humbly ask that you cite 35 * the research papers on the package. Check out http://www.gromacs.org. 36 */ 37 /*! \file 38 * \brief 39 * Declares fatal error handling and debugging routines for C code. 40 * 41 * \inpublicapi 42 * \ingroup module_utility 43 */ 44 #ifndef GMX_UTILITY_FATALERROR_H 45 #define GMX_UTILITY_FATALERROR_H 46 47 #include <stdarg.h> 48 #include <stdio.h> 49 50 #include "gromacs/utility/basedefinitions.h" 51 #include "gromacs/utility/stringutil.h" 52 53 /*! \brief 54 * Debug log file. 55 * 56 * Functions can write to this file for debug info. 57 * Before writing to it, it should be checked whether the file is not NULL: 58 * \code 59 if (debug) 60 { 61 fprintf(debug, "%s", "Debug text"); 62 } 63 \endcode 64 */ 65 extern FILE* debug; 66 /** Whether extra debugging is enabled. */ 67 extern gmx_bool gmx_debug_at; 68 69 /*! \brief 70 * Initializes debugging variables. 71 * 72 * This function is not threadsafe. It should be called as part of 73 * initializing \Gromacs, before any other thread accesses the library. 74 * For command line programs, gmx::CommandLineModuleManager takes care 75 * of this if the user requests debugging. 76 */ 77 void gmx_init_debug(int dbglevel, const char* dbgfile); 78 79 /** Returns TRUE when the program was started in debug mode */ 80 gmx_bool bDebugMode(); 81 82 /** Sets the log file for printing error messages. */ 83 void gmx_fatal_set_log_file(FILE* fp); 84 85 /** Function pointer type for fatal error handler callback. */ 86 typedef void (*gmx_error_handler_t)(const char* title, const std::string& msg, const char* file, int line); 87 88 /*! \brief 89 * Sets an error handler for gmx_fatal() and other fatal error routines. 90 * 91 * The default handler prints the message. 92 * \Gromacs will terminate the program after the error handler returns. 93 * To make gmx_fatal_collective() work, the error handler should not terminate 94 * the program, as it cannot know what is the desired way of termination. 95 * The message passed to the handler may be a multi-line string. 96 * 97 * \see gmx_fatal() 98 */ 99 void gmx_set_error_handler(gmx_error_handler_t func); 100 101 /** Identifies the state of the program on a fatal error. */ 102 enum ExitType 103 { 104 /*! \brief 105 * Clean exit is possible. 106 * 107 * There should be no concurrently executing code that might be accessing 108 * global objects, and all MPI ranks should reach the same fatal error. 109 */ 110 ExitType_CleanExit, 111 /*! \brief 112 * Program needs to be aborted. 113 * 114 * There are no preconditions for this state. 115 */ 116 ExitType_Abort, 117 /*! \brief 118 * Program needs to be aborted, but some other rank is responsible of it. 119 * 120 * There should be some other MPI rank that reaches the same fatal error, 121 * but uses ExitType_Abort. The other ranks can then use 122 * ExitType_NonMasterAbort to wait for that one rank to issue the abort. 123 */ 124 ExitType_NonMasterAbort 125 }; 126 127 /*! \brief 128 * Helper function to terminate the program on a fatal error. 129 * 130 * \param[in] exitType Identifies the state of the program at the time of the 131 * call, determining how the program can be terminated. 132 * \param[in] returnValue Exit code for the program, for cases where it can be 133 * used. 134 */ 135 [[noreturn]] void gmx_exit_on_fatal_error(enum ExitType exitType, int returnValue); 136 137 /*! \brief 138 * Low-level fatal error reporting routine for collective MPI errors. 139 * 140 * This function works as gmx_fatal(), but provides additional control for 141 * cases where it is known that the same error occurs on multiple MPI ranks. 142 * The error handler is called only if \p bMaster is `TRUE`, and MPI_Finalize() 143 * is called instead of MPI_Abort() in MPI-enabled \Gromacs if \p bFinalize is 144 * `TRUE`. 145 * 146 * This is used to implement gmx_fatal_collective() (which cannot be declared 147 * here, since it would bring with it mdrun-specific dependencies). 148 */ 149 [[noreturn]] void gmx_fatal_mpi_va(int fatal_errno, 150 const char* file, 151 int line, 152 gmx_bool bMaster, 153 gmx_bool bFinalize, 154 const char* fmt, 155 va_list ap); 156 157 /*! \brief 158 * Fatal error reporting routine for \Gromacs. 159 * 160 * This function prints a fatal error message with a header that contains the 161 * source file and line number of the call, followed by the string specified by 162 * \p fmt and supplied parameters. 163 * If \p fatal_errno is 0, only the message and arguments are printed. 164 * If \p fatal_errno is a legal system errno or -1, a perror()-like message is 165 * printed after the first message; if fatal_errno is -1, the last system errno 166 * will be used. 167 * The format of \p fmt uses printf()-like formatting. 168 * 169 * In case all MPI processes want to stop with the same fatal error, 170 * use gmx_fatal_collective(), declared in network.h, 171 * to avoid having as many error messages as processes. 172 * 173 * The first three parameters can be provided through ::FARGS: 174 * \code 175 gmx_fatal(FARGS, fmt, ...); 176 \endcode 177 */ 178 [[noreturn]] void gmx_fatal(int fatal_errno, const char* file, int line, gmx_fmtstr const char* fmt, ...) 179 gmx_format(printf, 4, 5); 180 /** Helper macro to pass first three parameters to gmx_fatal(). */ 181 #define FARGS 0, __FILE__, __LINE__ 182 183 /** Implementation for gmx_error(). */ 184 [[noreturn]] void _gmx_error(const char* key, const std::string& msg, const char* file, int line); 185 /*! \brief 186 * Alternative fatal error routine with canned messages. 187 * 188 * This works as gmx_fatal(), except that a generic error message is added 189 * based on a string key, and printf-style formatting is not supported. 190 * Should not typically be called directly, but through gmx_call() etc. 191 */ 192 #define gmx_error(key, msg) _gmx_error(key, msg, __FILE__, __LINE__) 193 194 /*! \name Fatal error routines for certain types of errors 195 * 196 * These wrap gmx_error() and provide the \p key parameter as one of the 197 * recognized strings. 198 */ 199 /*! \{ */ 200 #define gmx_call(msg) gmx_error("call", msg) 201 #define gmx_comm(msg) gmx_error("comm", msg) 202 #define gmx_file(msg) gmx_error("file", msg) 203 #define gmx_impl(msg) gmx_error("impl", msg) 204 #define gmx_incons(msg) gmx_error("incons", msg) 205 #define gmx_input(msg) gmx_error("input", msg) 206 #define gmx_mem(msg) gmx_error("mem", msg) 207 #define gmx_open(fn) gmx_error("open", fn) 208 /*! \} */ 209 210 /*! \brief 211 * Implementation for range_check() and range_check_mesg(). 212 * 213 * \p warn_str can be NULL. 214 */ 215 void _range_check(int n, int n_min, int n_max, const char* warn_str, const char* var, const char* file, int line); 216 217 /*! \brief 218 * Checks that a variable is within a range. 219 * 220 * If \p n is not in range [n_min, n_max), a fatal error is raised. 221 * \p n_min is inclusive, but \p n_max is not. 222 */ 223 #define range_check_mesg(n, n_min, n_max, str) \ 224 _range_check(n, n_min, n_max, str, #n, __FILE__, __LINE__) 225 226 /*! \brief 227 * Checks that a variable is within a range. 228 * 229 * This works as range_check_mesg(), but with a default error message. 230 */ 231 #define range_check(n, n_min, n_max) _range_check(n, n_min, n_max, NULL, #n, __FILE__, __LINE__) 232 233 /*! \brief 234 * Prints a warning message to stderr. 235 * 236 * The format of \p fmt uses printf()-like formatting. 237 * The message string should NOT start with "WARNING" 238 * and should NOT end with a newline. 239 */ 240 void gmx_warning(gmx_fmtstr const char* fmt, ...) gmx_format(printf, 1, 2); 241 242 #endif 243