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