1 /*============================================================================
2 * Base error handling
3 *============================================================================*/
4
5 /*
6 This file is part of Code_Saturne, a general-purpose CFD tool.
7
8 Copyright (C) 1998-2021 EDF S.A.
9
10 This program is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free Software
12 Foundation; either version 2 of the License, or (at your option) any later
13 version.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
18 details.
19
20 You should have received a copy of the GNU General Public License along with
21 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
22 Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 */
24
25 /*-----------------------------------------------------------------------------*/
26
27 #include "cs_defs.h"
28
29 /*-----------------------------------------------------------------------------*/
30
31 /*
32 * Standard C library headers
33 */
34
35 #include <assert.h>
36 #include <stdarg.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40
41 /*
42 * Optional library and BFT headers
43 */
44
45 #include "bft_printf.h"
46 #include "bft_error.h"
47
48 /*-----------------------------------------------------------------------------*/
49
50 BEGIN_C_DECLS
51
52 /*-----------------------------------------------------------------------------*/
53
54 /*-----------------------------------------------------------------------------
55 * Additional doxygen documentation
56 *-----------------------------------------------------------------------------*/
57
58 /* Associated typedef documentation (for bft_error.h) */
59
60 /*!
61 * \typedef bft_error_handler_t
62 *
63 * \brief Function pointer to opaque error handler.
64 *
65 * \param [in] file_name name of source file from which error handler
66 * called.
67 * \param [in] line_num line of source file from which error handler
68 * called.
69 * \param [in] sys_error_code error code if error in system or libc call,
70 * 0 otherwise.
71 * \param [in] format format string, as printf() and family.
72 * \param [in, out] arg_ptr pointer to variable argument list based on format
73 * string.
74 *
75 * In an MPI environment, it is recommended to replace the default
76 * error handler. This requires using the following headers:
77 *
78 * \snippet bft_error_example.c my_error_handler_headers
79 *
80 * An error handler function similar to the BFT default with MPI-awareness
81 * added looks like:
82 *
83 * \snippet bft_error_example.c my_error_handler_body
84 *
85 * In a more complex environment, \c MPI_COMM_WORLD could be replaced
86 * by another communicator.
87 */
88
89 /*! \cond DOXYGEN_SHOULD_SKIP_THIS */
90
91 /*-----------------------------------------------------------------------------
92 * Local type definitions
93 *-----------------------------------------------------------------------------*/
94
95 /*-----------------------------------------------------------------------------
96 * Local function prototypes
97 *-----------------------------------------------------------------------------*/
98
99 /*
100 * Default error handler.
101 *
102 * An error message is output to stderr (stdout is flushed first),
103 * and the current process is terminated.
104 *
105 * parameters:
106 * file_name: <-- name of source file from which error handler called.
107 * line_num: <-- line of source file from which error handler called.
108 * sys_error_code: <-- error code if error in system or libc call, 0 otherwise.
109 * format: <-- format string, as printf() and family.
110 * arg_ptr: <-> variable argument list based on format string.
111 */
112
113 static void
114 _bft_error_handler_default(const char *const file_name,
115 const int line_num,
116 const int sys_error_code,
117 const char *const format,
118 va_list arg_ptr);
119
120 /*-----------------------------------------------------------------------------
121 * Local static variable definitions
122 *-----------------------------------------------------------------------------*/
123
124 static bft_error_handler_t *_bft_error_handler = (_bft_error_handler_default);
125
126 /*-----------------------------------------------------------------------------
127 * Local function definitions
128 *-----------------------------------------------------------------------------*/
129
130 /*
131 * Default error handler.
132 *
133 * An error message is output to stderr (after bft_print_flush() is called),
134 * and the current process exits with an EXIT_FAILURE code.
135 *
136 * parameters:
137 * file_name: <-- name of source file from which error handler called.
138 * line_num: <-- line of source file from which error handler called.
139 * sys_error_code: <-- error code if error in system or libc call, 0 otherwise.
140 * format: <-- format string, as printf() and family.
141 * arg_ptr: <-> variable argument list based on format string.
142 */
143
144 static void
_bft_error_handler_default(const char * const file_name,const int line_num,const int sys_error_code,const char * const format,va_list arg_ptr)145 _bft_error_handler_default(const char *const file_name,
146 const int line_num,
147 const int sys_error_code,
148 const char *const format,
149 va_list arg_ptr)
150 {
151 bft_printf_flush();
152
153 fprintf(stderr, "\n");
154
155 if (sys_error_code != 0)
156 fprintf(stderr, _("\nSystem error: %s\n"), strerror(sys_error_code));
157
158 fprintf(stderr, _("\n%s:%d: Fatal error.\n\n"), file_name, line_num);
159
160 vfprintf(stderr, format, arg_ptr);
161
162 fprintf(stderr, "\n\n");
163
164 assert(0);
165
166 exit(EXIT_FAILURE);
167 }
168
169 /*! (DOXYGEN_SHOULD_SKIP_THIS) \endcond */
170
171 /*============================================================================
172 * Public function definitions
173 *============================================================================*/
174
175 /*!
176 * \brief Calls the error handler (set by bft_error_handler_set() or default).
177 *
178 * With the default error handler, bft_print_flush() is called, an error
179 * message is output to stderr, and the current process exits with an
180 * EXIT_FAILURE code.
181 *
182 * \param [in] file_name name of source file from which error handler
183 * called.
184 * \param [in] line_num line of source file from which error handler
185 * called.
186 * \param [in] sys_error_code error code if error in system or libc call,
187 * 0 otherwise.
188 * \param [in] format format string, as printf() and family.
189 * \param [in] ... variable arguments based on format string.
190 */
191
192 void
bft_error(const char * const file_name,const int line_num,const int sys_error_code,const char * const format,...)193 bft_error(const char *const file_name,
194 const int line_num,
195 const int sys_error_code,
196 const char *const format,
197 ...)
198 {
199 va_list arg_ptr;
200
201 va_start(arg_ptr, format);
202
203 _bft_error_handler(file_name, line_num, sys_error_code, format, arg_ptr);
204
205 va_end(arg_ptr);
206 }
207
208 /*!
209 * \brief Returns the error handler associated with the bft_error() function.
210 *
211 * \return pointer to the error handler function.
212 */
213
214 bft_error_handler_t *
bft_error_handler_get(void)215 bft_error_handler_get(void)
216 {
217 return _bft_error_handler;
218 }
219
220 /*!
221 * \brief Associates an error handler with the bft_error() function.
222 *
223 * \param [in] handler pointer to the error handler function.
224 */
225
226 void
bft_error_handler_set(bft_error_handler_t * const handler)227 bft_error_handler_set(bft_error_handler_t *const handler)
228 {
229 _bft_error_handler = handler;
230 }
231
232 /*-----------------------------------------------------------------------------*/
233
234 END_C_DECLS
235