BitShares-Core  7.0.2
BitShares blockchain node software and command-line wallet software
exception.hpp
Go to the documentation of this file.
1 #pragma once
2 
6 #include <fc/log/logger.hpp>
7 #include <fc/optional.hpp>
8 #include <exception>
9 #include <functional>
10 #include <unordered_map>
11 
12 namespace fc
13 {
14  namespace detail { class exception_impl; }
15 
17  {
40  };
41 
56  class exception
57  {
58  public:
59  enum code_enum
60  {
62  };
63 
65  const std::string& name_value = "exception",
66  const std::string& what_value = "unspecified");
68  const std::string& name_value = "exception",
69  const std::string& what_value = "unspecified");
71  const std::string& name_value = "exception",
72  const std::string& what_value = "unspecified");
73  exception( const log_messages&,
75  const std::string& name_value = "exception",
76  const std::string& what_value = "unspecified");
77  exception( const exception& e );
78  exception( exception&& e );
79  virtual ~exception();
80 
81  const char* name()const throw();
82  int64_t code()const throw();
83  virtual const char* what()const throw();
84 
89  const log_messages& get_log()const;
90  void append_log( log_message m );
91 
97  std::string to_detail_string( log_level ll = log_level::all )const;
98 
102  std::string to_string( log_level ll = log_level::info )const;
103 
109  [[noreturn]] virtual void dynamic_rethrow_exception()const;
110 
118  virtual std::shared_ptr<exception> dynamic_copy_exception()const;
119 
120  friend void to_variant( const exception& e, variant& v, uint32_t max_depth );
121  friend void from_variant( const variant& e, exception& ll, uint32_t max_depth );
122 
123  exception& operator=( const exception& copy );
124  exception& operator=( exception&& copy );
125  protected:
126  std::unique_ptr<detail::exception_impl> my;
127  };
128 
129  void to_variant( const exception& e, variant& v, uint32_t max_depth );
130  void from_variant( const variant& e, exception& ll, uint32_t max_depth );
131  typedef std::shared_ptr<exception> exception_ptr;
132 
134 
135 
147  {
148  public:
149  enum code_enum {
151  };
152  unhandled_exception( log_message&& m, std::exception_ptr e = std::current_exception() );
154  unhandled_exception( const exception& );
155 
156  std::exception_ptr get_inner_exception()const;
157 
158  [[noreturn]] virtual void dynamic_rethrow_exception()const;
159  virtual std::shared_ptr<exception> dynamic_copy_exception()const;
160  private:
161  std::exception_ptr _inner;
162  };
163 
164  template<typename T>
166  {
167 #if defined(_MSC_VER) && (_MSC_VER < 1700)
168  return std::make_shared<unhandled_exception>( log_message(),
169  std::copy_exception(std::forward<T>(e)) );
170 #else
171  return std::make_shared<unhandled_exception>( log_message(),
172  std::make_exception_ptr(std::forward<T>(e)) );
173 #endif
174  }
175 
176 
178  {
179  public:
181  {
182  [[noreturn]] virtual void rethrow( const exception& e )const = 0;
183  };
184 
185  template<typename T>
187  {
188  [[noreturn]] virtual void rethrow( const exception& e )const override
189  {
190  throw T( e );
191  }
192  };
193 
194  template<typename T>
196  {
197  static exception_builder<T> builder;
198  auto itr = _registered_exceptions.find( T::code_value );
199  assert( itr == _registered_exceptions.end() );
200  (void)itr; // in release builds this hides warnings
201  _registered_exceptions[T::code_value] = &builder;
202  }
203 
204  [[noreturn]] void rethrow( const exception& e )const;
205 
207  {
208  static exception_factory once;
209  return once;
210  }
211 
212  private:
213  std::unordered_map<int64_t,base_exception_builder*> _registered_exceptions;
214  };
215 #define FC_REGISTER_EXCEPTION(r, unused, base) \
216  fc::exception_factory::instance().register_exception<base>();
217 
218 #define FC_REGISTER_EXCEPTIONS( SEQ )\
219  \
220  static bool exception_init = []()->bool{ \
221  BOOST_PP_SEQ_FOR_EACH( FC_REGISTER_EXCEPTION, v, SEQ ) \
222  return true; \
223  }(); \
224 
225 
226 #define FC_DECLARE_DERIVED_EXCEPTION( TYPE, BASE, CODE ) \
227  class TYPE : public BASE \
228  { \
229  public: \
230  enum code_enum { \
231  code_value = CODE, \
232  }; \
233  explicit TYPE( int64_t code, const std::string& name_value, const std::string& what_value ); \
234  explicit TYPE( fc::log_message&& m, int64_t code, const std::string& name_value, const std::string& what_value ); \
235  explicit TYPE( fc::log_messages&& m, int64_t code, const std::string& name_value, const std::string& what_value );\
236  explicit TYPE( const fc::log_messages& m, int64_t code, const std::string& name_value, const std::string& what_value );\
237  explicit TYPE( const std::string& what_value, const fc::log_messages& m ); \
238  explicit TYPE( fc::log_message&& m ); \
239  explicit TYPE( fc::log_messages msgs ); \
240  TYPE( TYPE&& c ) = default; \
241  TYPE( const TYPE& c ); \
242  TYPE( const BASE& c ); \
243  explicit TYPE();\
244  \
245  virtual std::shared_ptr<fc::exception> dynamic_copy_exception()const;\
246  [[noreturn]] virtual void dynamic_rethrow_exception()const; \
247  };
248 
249 #define FC_IMPLEMENT_DERIVED_EXCEPTION( TYPE, BASE, CODE, WHAT ) \
250  TYPE::TYPE( int64_t code, const std::string& name_value, const std::string& what_value ) \
251  : BASE( code, name_value, what_value ) {} \
252  TYPE::TYPE( fc::log_message&& m, int64_t code, const std::string& name_value, const std::string& what_value ) \
253  : BASE( std::move(m), code, name_value, what_value ) {} \
254  TYPE::TYPE( fc::log_messages&& m, int64_t code, const std::string& name_value, const std::string& what_value ) \
255  : BASE( std::move(m), code, name_value, what_value ) {} \
256  TYPE::TYPE( const fc::log_messages& m, int64_t code, const std::string& name_value, const std::string& what_value ) \
257  : BASE( m, code, name_value, what_value ) {} \
258  TYPE::TYPE( const std::string& what_value, const fc::log_messages& m ) \
259  : BASE( m, CODE, BOOST_PP_STRINGIZE(TYPE), what_value ) {} \
260  TYPE::TYPE( fc::log_message&& m ) \
261  : BASE( std::move(m), CODE, BOOST_PP_STRINGIZE(TYPE), WHAT ) {} \
262  TYPE::TYPE( fc::log_messages msgs ) \
263  : BASE( std::move( msgs ), CODE, BOOST_PP_STRINGIZE(TYPE), WHAT ) {} \
264  TYPE::TYPE( const TYPE& c ) : BASE(c) {} \
265  TYPE::TYPE( const BASE& c ) : BASE(c) {} \
266  TYPE::TYPE() : BASE(CODE, BOOST_PP_STRINGIZE(TYPE), WHAT) {} \
267  \
268  std::shared_ptr<fc::exception> TYPE::dynamic_copy_exception()const \
269  { \
270  return std::make_shared<TYPE>( *this ); \
271  } \
272  [[noreturn]] void TYPE::dynamic_rethrow_exception()const \
273  { \
274  if( code() == CODE ) throw *this;\
275  else fc::exception::dynamic_rethrow_exception(); \
276  }
277 
278 #define FC_DECLARE_EXCEPTION( TYPE, CODE ) \
279  FC_DECLARE_DERIVED_EXCEPTION( TYPE, fc::exception, CODE )
280 
281 #define FC_IMPLEMENT_EXCEPTION( TYPE, CODE, WHAT ) \
282  FC_IMPLEMENT_DERIVED_EXCEPTION( TYPE, fc::exception, CODE, WHAT )
283 
284  FC_DECLARE_EXCEPTION( timeout_exception, timeout_exception_code );
285  FC_DECLARE_EXCEPTION( file_not_found_exception, file_not_found_exception_code );
289  FC_DECLARE_EXCEPTION( parse_error_exception, parse_error_exception_code );
290  FC_DECLARE_EXCEPTION( invalid_arg_exception, invalid_arg_exception_code );
294  FC_DECLARE_EXCEPTION( key_not_found_exception, key_not_found_exception_code );
295  FC_DECLARE_EXCEPTION( bad_cast_exception, bad_cast_exception_code );
296  FC_DECLARE_EXCEPTION( out_of_range_exception, out_of_range_exception_code );
297  FC_DECLARE_EXCEPTION( method_not_found_exception, method_not_found_exception_code );
298 
300  FC_DECLARE_EXCEPTION( invalid_operation_exception, invalid_operation_exception_code );
302  FC_DECLARE_EXCEPTION( unknown_host_exception, unknown_host_exception_code );
303 
307  FC_DECLARE_EXCEPTION( canceled_exception, canceled_exception_code );
311  FC_DECLARE_EXCEPTION( assert_exception, assert_exception_code );
312  FC_DECLARE_EXCEPTION( eof_exception, eof_exception_code );
313  FC_DECLARE_EXCEPTION( null_optional, null_optional_code );
314  FC_DECLARE_EXCEPTION( aes_exception, aes_error_code );
315  FC_DECLARE_EXCEPTION( overflow_exception, overflow_code );
317  FC_DECLARE_EXCEPTION( divide_by_zero_exception, divide_by_zero_code );
318 
319  std::string except_str();
320 
321  void record_assert_trip(
322  const char* filename,
323  uint32_t lineno,
324  const char* expr
325  );
326 
327  extern bool enable_record_assert_trip;
328 } // namespace fc
329 
330 #if __APPLE__
331  #define LIKELY(x) __builtin_expect((long)!!(x), 1L)
332  #define UNLIKELY(x) __builtin_expect((long)!!(x), 0L)
333 #else
334  #define LIKELY(x) (x)
335  #define UNLIKELY(x) (x)
336 #endif
337 
341 #define FC_EXPAND_MACRO( x ) x
342 
345 #define FC_ASSERT( TEST, ... ) \
346  FC_EXPAND_MACRO( \
347  FC_MULTILINE_MACRO_BEGIN \
348  if( UNLIKELY(!(TEST)) ) \
349  { \
350  if( fc::enable_record_assert_trip ) \
351  fc::record_assert_trip( __FILE__, __LINE__, #TEST ); \
352  FC_THROW_EXCEPTION( fc::assert_exception, #TEST ": " __VA_ARGS__ ); \
353  } \
354  FC_MULTILINE_MACRO_END \
355  )
356 
357 #define FC_CAPTURE_AND_THROW( EXCEPTION_TYPE, ... ) \
358  FC_MULTILINE_MACRO_BEGIN \
359  throw EXCEPTION_TYPE( FC_LOG_MESSAGE( error, "", FC_FORMAT_ARG_PARAMS(__VA_ARGS__) ) ); \
360  FC_MULTILINE_MACRO_END
361 
362 //#define FC_THROW( FORMAT, ... )
363 // FC_INDIRECT_EXPAND workas around a bug in Visual C++ variadic macro processing that prevents it
364 // from separating __VA_ARGS__ into separate tokens
365 #define FC_INDIRECT_EXPAND(MACRO, ARGS) MACRO ARGS
366 #define FC_THROW( ... ) \
367  FC_MULTILINE_MACRO_BEGIN \
368  throw fc::exception( FC_INDIRECT_EXPAND(FC_LOG_MESSAGE, ( error, __VA_ARGS__ )) ); \
369  FC_MULTILINE_MACRO_END
370 
371 #define FC_EXCEPTION( EXCEPTION_TYPE, FORMAT, ... ) \
372  EXCEPTION_TYPE( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) )
373 
379 #define FC_THROW_EXCEPTION( EXCEPTION, FORMAT, ... ) \
380  FC_MULTILINE_MACRO_BEGIN \
381  throw EXCEPTION( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) ); \
382  FC_MULTILINE_MACRO_END
383 
384 
389 #define FC_RETHROW_EXCEPTION( ER, LOG_LEVEL, FORMAT, ... ) \
390  FC_MULTILINE_MACRO_BEGIN \
391  ER.append_log( FC_LOG_MESSAGE( LOG_LEVEL, FORMAT, __VA_ARGS__ ) ); \
392  throw; \
393  FC_MULTILINE_MACRO_END
394 
395 #define FC_LOG_AND_RETHROW( ) \
396  catch( fc::exception& er ) { \
397  wlog( "${details}", ("details",er.to_detail_string()) ); \
398  FC_RETHROW_EXCEPTION( er, warn, "rethrow" ); \
399  } catch( const std::exception& e ) { \
400  fc::exception fce( \
401  FC_LOG_MESSAGE( warn, "rethrow ${what}: ", ("what",e.what())), \
402  fc::std_exception_code,\
403  typeid(e).name(), \
404  e.what() ) ; \
405  wlog( "${details}", ("details",fce.to_detail_string()) ); \
406  throw fce;\
407  } catch( ... ) { \
408  fc::unhandled_exception e( \
409  FC_LOG_MESSAGE( warn, "rethrow"), \
410  std::current_exception() ); \
411  wlog( "${details}", ("details",e.to_detail_string()) ); \
412  throw e; \
413  }
414 
415 #define FC_CAPTURE_LOG_AND_RETHROW( ... ) \
416  catch( fc::exception& er ) { \
417  wlog( "${details}", ("details",er.to_detail_string()) ); \
418  wdump( __VA_ARGS__ ); \
419  FC_RETHROW_EXCEPTION( er, warn, "rethrow", FC_FORMAT_ARG_PARAMS(__VA_ARGS__) ); \
420  } catch( const std::exception& e ) { \
421  fc::exception fce( \
422  FC_LOG_MESSAGE( warn, "rethrow ${what}: ", FC_FORMAT_ARG_PARAMS( __VA_ARGS__ )("what",e.what())), \
423  fc::std_exception_code,\
424  typeid(e).name(), \
425  e.what() ) ; \
426  wlog( "${details}", ("details",fce.to_detail_string()) ); \
427  wdump( __VA_ARGS__ ); \
428  throw fce;\
429  } catch( ... ) { \
430  fc::unhandled_exception e( \
431  FC_LOG_MESSAGE( warn, "rethrow", FC_FORMAT_ARG_PARAMS( __VA_ARGS__) ), \
432  std::current_exception() ); \
433  wlog( "${details}", ("details",e.to_detail_string()) ); \
434  wdump( __VA_ARGS__ ); \
435  throw e; \
436  }
437 
438 #define FC_CAPTURE_AND_LOG( ... ) \
439  catch( fc::exception& er ) { \
440  wlog( "${details}", ("details",er.to_detail_string()) ); \
441  wdump( __VA_ARGS__ ); \
442  } catch( const std::exception& e ) { \
443  fc::exception fce( \
444  FC_LOG_MESSAGE( warn, "rethrow ${what}: ",FC_FORMAT_ARG_PARAMS( __VA_ARGS__ )("what",e.what()) ), \
445  fc::std_exception_code,\
446  typeid(e).name(), \
447  e.what() ) ; \
448  wlog( "${details}", ("details",fce.to_detail_string()) ); \
449  wdump( __VA_ARGS__ ); \
450  } catch( ... ) { \
451  fc::unhandled_exception e( \
452  FC_LOG_MESSAGE( warn, "rethrow", FC_FORMAT_ARG_PARAMS( __VA_ARGS__) ), \
453  std::current_exception() ); \
454  wlog( "${details}", ("details",e.to_detail_string()) ); \
455  wdump( __VA_ARGS__ ); \
456  }
457 
458 
464 #define FC_RETHROW_EXCEPTIONS( LOG_LEVEL, FORMAT, ... ) \
465  catch( fc::exception& er ) { \
466  FC_RETHROW_EXCEPTION( er, LOG_LEVEL, FORMAT, __VA_ARGS__ ); \
467  } catch( const std::exception& e ) { \
468  throw fc::exception( \
469  FC_LOG_MESSAGE( LOG_LEVEL, "${what}: " FORMAT,__VA_ARGS__("what",e.what())), \
470  fc::std_exception_code,\
471  typeid(e).name(), \
472  e.what() ) ;\
473  } catch( ... ) { \
474  throw fc::unhandled_exception( \
475  FC_LOG_MESSAGE( LOG_LEVEL, FORMAT,__VA_ARGS__), \
476  std::current_exception() ); \
477  }
478 
479 #define FC_CAPTURE_AND_RETHROW( ... ) \
480  catch( fc::exception& er ) { \
481  FC_RETHROW_EXCEPTION( er, warn, "", FC_FORMAT_ARG_PARAMS(__VA_ARGS__) ); \
482  } catch( const std::exception& e ) { \
483  throw fc::exception( \
484  FC_LOG_MESSAGE( warn, "${what}: ",FC_FORMAT_ARG_PARAMS(__VA_ARGS__)("what",e.what())), \
485  fc::std_exception_code,\
486  typeid(e).name(), \
487  e.what() ) ;\
488  } catch( ... ) { \
489  throw fc::unhandled_exception( \
490  FC_LOG_MESSAGE( warn, "",FC_FORMAT_ARG_PARAMS(__VA_ARGS__)), \
491  std::current_exception() ); \
492  }
493 
fc::file_not_found_exception_code
@ file_not_found_exception_code
Definition: exception.hpp:22
fc::copy
void copy(const path &from, const path &to)
Definition: filesystem.cpp:241
fc::aes_error_code
@ aes_error_code
Definition: exception.hpp:35
fc::exception
Used to generate a useful error report when an exception is thrown.
Definition: exception.hpp:56
fc::exception_factory::base_exception_builder
Definition: exception.hpp:180
fc::exception::get_log
const log_messages & get_log() const
Definition: exception.cpp:172
fc::exception::to_variant
friend void to_variant(const exception &e, variant &v, uint32_t max_depth)
Definition: exception.cpp:145
fc::exception_factory::exception_builder
Definition: exception.hpp:186
fc::overflow_code
@ overflow_code
Definition: exception.hpp:36
fc::invalid_arg_exception_code
@ invalid_arg_exception_code
Definition: exception.hpp:24
fc::unknown_host_exception_code
@ unknown_host_exception_code
Definition: exception.hpp:33
fc::exception::code
int64_t code() const
Definition: exception.cpp:141
fc
Definition: api.hpp:15
fc::underflow_code
@ underflow_code
Definition: exception.hpp:37
fc::divide_by_zero_code
@ divide_by_zero_code
Definition: exception.hpp:38
fc::exception::append_log
void append_log(log_message m)
Definition: exception.cpp:173
fc::exception::~exception
virtual ~exception()
Definition: exception.cpp:143
fc::exception::what
virtual const char * what() const
Definition: exception.cpp:140
fc::bad_cast_exception_code
@ bad_cast_exception_code
Definition: exception.hpp:26
fc::enable_record_assert_trip
bool enable_record_assert_trip
Definition: exception.cpp:337
fc::FC_DECLARE_EXCEPTION
FC_DECLARE_EXCEPTION(timeout_exception, timeout_exception_code)
fc::exception_ptr
std::shared_ptr< exception > exception_ptr
Definition: exception.hpp:131
fc::invalid_operation_exception_code
@ invalid_operation_exception_code
Definition: exception.hpp:32
fc::exception::code_enum
code_enum
Definition: exception.hpp:59
fc::exception_factory::register_exception
void register_exception()
Definition: exception.hpp:195
fc::null_optional_code
@ null_optional_code
Definition: exception.hpp:34
fc::exception::exception
exception(int64_t code=unspecified_exception_code, const std::string &name_value="exception", const std::string &what_value="unspecified")
Definition: exception.cpp:112
fc::exception::name
const char * name() const
Definition: exception.cpp:139
fc::exception_code
exception_code
Definition: exception.hpp:16
fc::exception_factory::instance
static exception_factory & instance()
Definition: exception.hpp:206
fc::exception::to_string
std::string to_string(log_level ll=log_level::info) const
Definition: exception.cpp:227
fc::record_assert_trip
void record_assert_trip(const char *filename, uint32_t lineno, const char *expr)
Definition: exception.cpp:313
fc::assert_exception_code
@ assert_exception_code
Definition: exception.hpp:29
fc::exception::my
std::unique_ptr< detail::exception_impl > my
Definition: exception.hpp:126
fc::exception::dynamic_rethrow_exception
virtual void dynamic_rethrow_exception() const
Definition: exception.cpp:262
fc::key_not_found_exception_code
@ key_not_found_exception_code
Definition: exception.hpp:25
fc::exception::to_detail_string
std::string to_detail_string(log_level ll=log_level::all) const
Definition: exception.cpp:183
fc::exception::dynamic_copy_exception
virtual std::shared_ptr< exception > dynamic_copy_exception() const
Definition: exception.cpp:267
fc::exception_factory
Definition: exception.hpp:177
fc::unspecified_exception_code
@ unspecified_exception_code
Definition: exception.hpp:19
fc::underflow_exception
() file_not_found_exception() parse_error_exception() invalid_arg_exception() invalid_operation_exception() key_not_found_exception() bad_cast_exception() out_of_range_exception() canceled_exception() assert_exception() eof_exception() unknown_host_exception() null_optional() aes_exception() overflow_exception() underflow_exception(divide_by_zero_exception)) namespace detail
Definition: exception.cpp:46
fc::log_message
aggregates a message along with the context and associated meta-information.
Definition: log_message.hpp:106
fc::unhandled_exception
re-thrown whenever an unhandled exception is caught.
Definition: exception.hpp:146
fc::variant
stores null, int64, uint64, double, bool, string, std::vector<variant>, and variant_object's.
Definition: variant.hpp:198
fc::unhandled_exception_code
@ unhandled_exception_code
for unhandled 3rd party exceptions
Definition: exception.hpp:20
fc::eof_exception_code
@ eof_exception_code
Definition: exception.hpp:30
std
Definition: zeroed_array.hpp:76
fc::log_messages
std::vector< log_message > log_messages
Definition: log_message.hpp:134
fc::std_exception_code
@ std_exception_code
Definition: exception.hpp:31
fc::canceled_exception_code
@ canceled_exception_code
Definition: exception.hpp:28
logger.hpp
fc::copy_exception
fc::exception_ptr copy_exception(T &&e)
Definition: exception.hpp:165
fc::parse_error_exception_code
@ parse_error_exception_code
Definition: exception.hpp:23
fc::method_not_found_exception_code
@ method_not_found_exception_code
Definition: exception.hpp:39
fc::exception::code_value
@ code_value
Definition: exception.hpp:61
fc::log_level
Definition: log_message.hpp:23
fc::exception_factory::exception_builder::rethrow
virtual void rethrow(const exception &e) const override
Definition: exception.hpp:188
fc::optional
provides stack-based nullable value similar to boost::optional
Definition: optional.hpp:20
fc::except_str
std::string except_str()
Definition: exception.cpp:272
fc::exception::from_variant
friend void from_variant(const variant &e, exception &ll, uint32_t max_depth)
Definition: exception.cpp:158
fc::timeout_exception_code
@ timeout_exception_code
timeout exceptions
Definition: exception.hpp:21
fc::out_of_range_exception_code
@ out_of_range_exception_code
Definition: exception.hpp:27
optional.hpp