Nektar++
ErrorUtil.hpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File ErrorUtil.hpp
4 //
5 // For more information, please see: http://www.nektar.info
6 //
7 // The MIT License
8 //
9 // Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10 // Department of Aeronautics, Imperial College London (UK), and Scientific
11 // Computing and Imaging Institute, University of Utah (USA).
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining a
14 // copy of this software and associated documentation files (the "Software"),
15 // to deal in the Software without restriction, including without limitation
16 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 // and/or sell copies of the Software, and to permit persons to whom the
18 // Software is furnished to do so, subject to the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be included
21 // in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 // DEALINGS IN THE SOFTWARE.
30 //
31 // Description: error related utilities
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 #ifndef ERRORUTIL_HPP
35 #define ERRORUTIL_HPP
36 
37 #include <iostream>
38 #include <stdexcept>
39 #include <string>
40 
41 #include <boost/core/ignore_unused.hpp>
42 
44 
45 #if defined(NEKTAR_USE_MPI)
46 #include <mpi.h>
47 #endif
48 
49 #ifndef _WIN32
50 #include <execinfo.h>
51 #endif
52 
53 namespace Nektar
54 {
55 
56 class ErrorUtil
57 {
58 public:
59  class NekError : public std::runtime_error
60  {
61  public:
62  NekError(const std::string& message) : std::runtime_error(message)
63  {
64  }
65  };
66 
67  enum ErrType
68  {
71  };
72 
73  inline static void SetErrorStream(std::ostream& o)
74  {
75  m_outStream = &o;
76  }
77 
78  inline static void SetPrintBacktrace(bool b)
79  {
80  m_printBacktrace = b;
81  }
82 
83  inline static bool HasCustomErrorStream()
84  {
85  return m_outStream != &std::cerr;
86  }
87 
88  inline static void Error(ErrType type,
89  const char *routine,
90  int lineNumber,
91  const char *msg,
92  unsigned int level,
93  bool DoComm = false)
94  {
95  boost::ignore_unused(DoComm);
96 
97  // The user of outStream is primarily for the unit tests. The unit
98  // tests often generate errors on purpose to make sure invalid usage is
99  // flagged appropriately. Printing the error messages to cerr made the
100  // unit test output hard to parse.
101 
102  std::string baseMsg = "Level " + std::to_string(level) +
103  " assertion violation\n";
104 #if defined(NEKTAR_DEBUG) || defined(NEKTAR_FULLDEBUG)
105  baseMsg += "Where : " + std::string(routine) + "[" +
106  std::to_string(lineNumber) + "]\n Message : ";
107 #else
108  boost::ignore_unused(routine, lineNumber);
109 #endif
110  baseMsg += std::string(msg);
111 
112  // Default rank is zero. If MPI used and initialised, populate with
113  // the correct rank. Messages are only printed on rank zero.
114  int rank = 0;
115 #if defined(NEKTAR_USE_MPI) && !defined(NEKTAR_USE_CWIPI)
116  int flag = 0;
117  if(DoComm)
118  {
119  MPI_Initialized(&flag);
120  if(flag)
121  {
122  MPI_Comm_rank(MPI_COMM_WORLD,&rank);
123  }
124  }
125 #else
126  boost::ignore_unused(DoComm);
127 #endif
128 
129  std::string btMessage("");
130 #if defined(NEKTAR_FULLDEBUG)
131 #ifndef _WIN32
132  if (m_printBacktrace)
133  {
134  void *btArray[40];
135  int btSize;
136  char **btStrings;
137 
138  btSize = backtrace(btArray, 40);
139  btStrings = backtrace_symbols(btArray, btSize);
140 
141  for (int i = 0 ; i < btSize ; ++i)
142  {
143  btMessage += std::string(btStrings[i]) + "\n";
144  }
145  free(btStrings);
146  }
147 #endif
148 #endif
149 
150  switch (type)
151  {
152  case efatal:
153  if (!rank)
154  {
155  if (m_printBacktrace)
156  {
157  (*m_outStream) << btMessage;
158  }
159  (*m_outStream) << "Fatal : " << baseMsg << std::endl;
160  }
161 
162 #if defined(NEKTAR_USE_MPI) && !defined(NEKTAR_USE_CWIPI)
163  if(DoComm)
164  {
165  if (flag)
166  {
167  MPI_Barrier(MPI_COMM_WORLD);
168  }
169  }
170 #endif
171  throw NekError(baseMsg);
172  break;
173  case ewarning:
174  if (!rank)
175  {
176  if (m_printBacktrace)
177  {
178  (*m_outStream) << btMessage;
179  }
180  (*m_outStream) << "Warning: " << baseMsg << std::endl;
181  }
182  break;
183  default:
184  (*m_outStream) << "Unknown warning type: " << baseMsg << std::endl;
185  }
186  }
187 
188  inline static void Error(ErrType type, const char *routine, int lineNumber, const std::string& msg, unsigned int level)
189  {
190  Error(type, routine, lineNumber, msg.c_str(), level);
191  }
192 
193  inline static void Error(ErrType type, const char *routine, int lineNumber, const char *msg)
194  {
195  Error(type, routine, lineNumber, msg, 0);
196  }
197 
198 private:
199  LIB_UTILITIES_EXPORT static std::ostream *m_outStream;
201 };
202 
203 /// Assert Level 0 -- Fundamental assert which
204 /// is used whether in FULLDEBUG, DEBUG or OPT
205 /// compilation mode. This level assert is
206 /// considered code critical, even under
207 /// optimized compilation.
208 
209 #define NEKERROR(type, msg) \
210  Nektar::ErrorUtil::Error(type, __FILE__, __LINE__, msg, 0);
211 
212 
213 #define ROOTONLY_NEKERROR(type, msg) \
214  Nektar::ErrorUtil::Error(type, __FILE__, __LINE__, msg, 0, true);
215 
216 #define ASSERTL0(condition,msg) \
217  if(!(condition)) \
218  { \
219  Nektar::ErrorUtil::Error( \
220  Nektar::ErrorUtil::efatal, __FILE__, __LINE__, msg, 0); \
221  }
222 
223 #define WARNINGL0(condition,msg) \
224  if(!(condition)) \
225  { \
226  Nektar::ErrorUtil::Error( \
227  Nektar::ErrorUtil::ewarning, __FILE__, __LINE__, msg, 0); \
228  }
229 
230 /// Assert Level 1 -- Debugging which is used whether in FULLDEBUG or
231 /// DEBUG compilation mode. This level assert is designed for aiding
232 /// in standard debug (-g) mode
233 #if defined(NEKTAR_DEBUG) || defined(NEKTAR_FULLDEBUG)
234 
235 #define ASSERTL1(condition,msg) \
236  if(!(condition)) \
237  { \
238  Nektar::ErrorUtil::Error( \
239  Nektar::ErrorUtil::efatal, __FILE__, __LINE__, msg, 1); \
240  }
241 
242 #define WARNINGL1(condition,msg) \
243  if(!(condition)) \
244  { \
245  Nektar::ErrorUtil::Error( \
246  Nektar::ErrorUtil::ewarning, __FILE__, __LINE__, msg, 1); \
247  }
248 
249 #else //defined(NEKTAR_DEBUG) || defined(NEKTAR_FULLDEBUG)
250 #define ASSERTL1(condition,msg)
251 #define WARNINGL1(condition,msg)
252 #endif //defined(NEKTAR_DEBUG) || defined(NEKTAR_FULLDEBUG)
253 
254 
255 /// Assert Level 2 -- Debugging which is used FULLDEBUG compilation
256 /// mode. This level assert is designed to provide addition safety
257 /// checks within the code (such as bounds checking, etc.).
258 #ifdef NEKTAR_FULLDEBUG
259 
260 #define ASSERTL2(condition,msg) \
261  if(!(condition)) \
262  { \
263  Nektar::ErrorUtil::Error( \
264  Nektar::ErrorUtil::efatal, __FILE__, __LINE__, msg, 2); \
265  }
266 #define WARNINGL2(condition,msg) \
267  if(!(condition)) \
268  { \
269  Nektar::ErrorUtil::Error( \
270  Nektar::ErrorUtil::ewarning, __FILE__, __LINE__, msg, 2); \
271  }
272 
273 #else //NEKTAR_FULLDEBUG
274 #define ASSERTL2(condition,msg)
275 #define WARNINGL2(condition,msg)
276 #endif //NEKTAR_FULLDEBUG
277 
278 }
279 
280 #endif //ERRORUTIL_HPP
281 
static bool m_printBacktrace
Definition: ErrorUtil.hpp:200
static void SetPrintBacktrace(bool b)
Definition: ErrorUtil.hpp:78
STL namespace.
static bool HasCustomErrorStream()
Definition: ErrorUtil.hpp:83
static std::ostream * m_outStream
Definition: ErrorUtil.hpp:199
#define LIB_UTILITIES_EXPORT
NekError(const std::string &message)
Definition: ErrorUtil.hpp:62
static void SetErrorStream(std::ostream &o)
Definition: ErrorUtil.hpp:73
static void Error(ErrType type, const char *routine, int lineNumber, const char *msg)
Definition: ErrorUtil.hpp:193
static void Error(ErrType type, const char *routine, int lineNumber, const std::string &msg, unsigned int level)
Definition: ErrorUtil.hpp:188
static void Error(ErrType type, const char *routine, int lineNumber, const char *msg, unsigned int level, bool DoComm=false)
Definition: ErrorUtil.hpp:88