BitShares-Core  7.0.2
BitShares blockchain node software and command-line wallet software
exception.cpp
Go to the documentation of this file.
2 #include <boost/exception/all.hpp>
3 #include <fc/io/sstream.hpp>
4 #include <fc/log/logger.hpp>
5 #include <fc/io/json.hpp>
6 
7 #include <iostream>
8 
9 namespace fc
10 {
11  FC_IMPLEMENT_EXCEPTION( timeout_exception, timeout_exception_code, "Timeout" )
12  FC_IMPLEMENT_EXCEPTION( file_not_found_exception, file_not_found_exception_code, "File Not Found" )
13  FC_IMPLEMENT_EXCEPTION( parse_error_exception, parse_error_exception_code, "Parse Error" )
14  FC_IMPLEMENT_EXCEPTION( invalid_arg_exception, invalid_arg_exception_code, "Invalid Argument" )
15  FC_IMPLEMENT_EXCEPTION( key_not_found_exception, key_not_found_exception_code, "Key Not Found" )
16  FC_IMPLEMENT_EXCEPTION( bad_cast_exception, bad_cast_exception_code, "Bad Cast" )
17  FC_IMPLEMENT_EXCEPTION( out_of_range_exception, out_of_range_exception_code, "Out of Range" )
18  FC_IMPLEMENT_EXCEPTION( method_not_found_exception, method_not_found_exception_code, "Method Not Found" );
19  FC_IMPLEMENT_EXCEPTION( invalid_operation_exception, invalid_operation_exception_code, "Invalid Operation" )
20  FC_IMPLEMENT_EXCEPTION( unknown_host_exception, unknown_host_exception_code, "Unknown Host" )
21  FC_IMPLEMENT_EXCEPTION( canceled_exception, canceled_exception_code, "Canceled" )
22  FC_IMPLEMENT_EXCEPTION( assert_exception, assert_exception_code, "Assert Exception" )
23  FC_IMPLEMENT_EXCEPTION( eof_exception, eof_exception_code, "End Of File" )
24  FC_IMPLEMENT_EXCEPTION( null_optional, null_optional_code, "null optional" )
25  FC_IMPLEMENT_EXCEPTION( aes_exception, aes_error_code, "AES error" )
26  FC_IMPLEMENT_EXCEPTION( overflow_exception, overflow_code, "Integer Overflow" )
28  FC_IMPLEMENT_EXCEPTION( divide_by_zero_exception, divide_by_zero_code, "Integer Divide By Zero" )
29 
30  FC_REGISTER_EXCEPTIONS( (timeout_exception)
31  (file_not_found_exception)
32  (parse_error_exception)
33  (invalid_arg_exception)
34  (invalid_operation_exception)
35  (key_not_found_exception)
36  (bad_cast_exception)
37  (out_of_range_exception)
38  (canceled_exception)
39  (assert_exception)
40  (eof_exception)
41  (unknown_host_exception)
42  (null_optional)
43  (aes_exception)
44  (overflow_exception)
46  (divide_by_zero_exception)
47  )
48 
49  namespace detail
50  {
51  class exception_impl
52  {
53  public:
54  std::string _name;
55  std::string _what;
56  int64_t _code;
57  log_messages _elog;
58  };
59  }
60  exception::exception( log_messages&& msgs, int64_t code,
61  const std::string& name_value,
62  const std::string& what_value )
63  :my( new detail::exception_impl() )
64  {
65  my->_code = code;
66  my->_what = what_value;
67  my->_name = name_value;
68  my->_elog = std::move(msgs);
69  }
70 
72  const log_messages& msgs,
73  int64_t code,
74  const std::string& name_value,
75  const std::string& what_value )
76  :my( new detail::exception_impl() )
77  {
78  my->_code = code;
79  my->_what = what_value;
80  my->_name = name_value;
81  my->_elog = msgs;
82  }
83 
85  :exception( std::move(m) )
86  {
87  _inner = e;
88  }
90  :exception(r)
91  {
92  }
94  :exception()
95  { my->_elog = std::move(m); }
96 
98 
100  {
101  if( !(_inner == std::exception_ptr()) ) std::rethrow_exception( _inner );
103  }
104 
105  std::shared_ptr<exception> unhandled_exception::dynamic_copy_exception()const
106  {
107  auto e = std::make_shared<unhandled_exception>( *this );
108  e->_inner = _inner;
109  return e;
110  }
111 
112  exception::exception( int64_t code,
113  const std::string& name_value,
114  const std::string& what_value )
115  :my( new detail::exception_impl() )
116  {
117  my->_code = code;
118  my->_what = what_value;
119  my->_name = name_value;
120  }
121 
123  int64_t code,
124  const std::string& name_value,
125  const std::string& what_value )
126  :my( new detail::exception_impl() )
127  {
128  my->_code = code;
129  my->_what = what_value;
130  my->_name = name_value;
131  my->_elog.push_back( std::move( msg ) );
132  }
134  :my( new detail::exception_impl(*c.my) )
135  { }
137  :my( std::move(c.my) ){}
138 
139  const char* exception::name()const throw() { return my->_name.c_str(); }
140  const char* exception::what()const throw() { return my->_what.c_str(); }
141  int64_t exception::code()const throw() { return my->_code; }
142 
144 
145  void to_variant( const exception& e, variant& v, uint32_t max_depth )
146  {
147  FC_ASSERT( max_depth > 0, "Recursion depth exceeded!" );
148  variant v_log;
149  to_variant( e.get_log(), v_log, max_depth - 1 );
151  tmp( "code", e.code() )
152  ( "name", e.name() )
153  ( "message", e.what() )
154  ( "stack", v_log );
155  v = variant( tmp, max_depth );
156 
157  }
158  void from_variant( const variant& v, exception& ll, uint32_t max_depth )
159  {
160  FC_ASSERT( max_depth > 0, "Recursion depth exceeded!" );
161  auto obj = v.get_object();
162  if( obj.contains( "stack" ) )
163  ll.my->_elog = obj["stack"].as<log_messages>( max_depth - 1 );
164  if( obj.contains( "code" ) )
165  ll.my->_code = obj["code"].as_int64();
166  if( obj.contains( "name" ) )
167  ll.my->_name = obj["name"].as_string();
168  if( obj.contains( "message" ) )
169  ll.my->_what = obj["message"].as_string();
170  }
171 
172  const log_messages& exception::get_log()const { return my->_elog; }
174  {
175  my->_elog.emplace_back( std::move(m) );
176  }
177 
184  {
185  std::stringstream ss;
186  try {
187  try {
188  ss << variant( my->_code ).as_string();
189  } catch( std::bad_alloc& ) {
190  throw;
191  } catch( ... ) {
192  ss << "<- exception in to_detail_string.";
193  }
194  ss << " " << my->_name << ": " << my->_what << "\n";
195  for( auto itr = my->_elog.begin(); itr != my->_elog.end(); )
196  {
197  try {
198  ss << itr->get_message() <<"\n";
199  try
200  {
201  ss << " " << json::to_string( itr->get_data() )<<"\n";
202  }
203  catch( const fc::assert_exception& e )
204  {
205  ss << "ERROR: Failed to convert log data to string!\n";
206  }
207  ss << " " << itr->get_context().to_string();
208  } catch( std::bad_alloc& ) {
209  throw;
210  } catch( ... ) {
211  ss << "<- exception in to_detail_string.";
212  }
213  ++itr;
214  if( itr != my->_elog.end() ) ss<<"\n";
215  }
216  } catch( std::bad_alloc& ) {
217  throw;
218  } catch( ... ) {
219  ss << "<- exception in to_detail_string.\n";
220  }
221  return ss.str();
222  }
223 
227  string exception::to_string( log_level ll )const
228  {
229  std::stringstream ss;
230  try {
231  ss << what() << ":";
232  for( auto itr = my->_elog.begin(); itr != my->_elog.end(); ++itr ) {
233  if( itr->get_format().size() )
234  try {
235  ss << " " << fc::format_string( itr->get_format(), itr->get_data() );
236  } catch( std::bad_alloc& ) {
237  throw;
238  } catch( ... ) {
239  ss << "<- exception in to_string.\n";
240  }
241  }
242  } catch( std::bad_alloc& ) {
243  throw;
244  } catch( ... ) {
245  ss << "<- exception in to_string.\n";
246  }
247  return ss.str();
248  }
249 
250  [[noreturn]] void exception_factory::rethrow( const exception& e )const
251  {
252  auto itr = _registered_exceptions.find( e.code() );
253  if( itr != _registered_exceptions.end() )
254  itr->second->rethrow( e );
255  throw e;
256  }
262  [[noreturn]] void exception::dynamic_rethrow_exception()const
263  {
265  }
266 
268  {
269  return std::make_shared<exception>(*this);
270  }
271 
272  std::string except_str()
273  {
274  return boost::current_exception_diagnostic_information();
275  }
276 
277  void throw_bad_enum_cast( int64_t i, const char* e )
278  {
279  FC_THROW_EXCEPTION( bad_cast_exception,
280  "invalid index '${key}' in enum '${enum}'",
281  ("key",i)("enum",e) );
282  }
283  void throw_bad_enum_cast( const char* k, const char* e )
284  {
285  FC_THROW_EXCEPTION( bad_cast_exception,
286  "invalid name '${key}' in enum '${enum}'",
287  ("key",k)("enum",e) );
288  }
289 
290  bool assert_optional(bool is_valid )
291  {
292  if( !is_valid )
293  throw null_optional();
294  return true;
295  }
297  {
298  *my = *copy.my;
299  return *this;
300  }
301 
303  {
304  my = std::move(copy.my);
305  return *this;
306  }
307 
308  void throw_assertion_failure( const std::string& message )
309  {
310  FC_THROW_EXCEPTION( fc::assert_exception, message );
311  }
312 
314  const char* filename,
315  uint32_t lineno,
316  const char* expr
317  )
318  {
319  fc::mutable_variant_object assert_trip_info =
321  ("source_file", filename)
322  ("source_lineno", lineno)
323  ("expr", expr)
324  ;
325  try
326  {
327  std::cout
328  << "FC_ASSERT triggered: "
329  << fc::json::to_string( assert_trip_info ) << "\n";
330  }
331  catch( const fc::assert_exception& e )
332  { // this should never happen. assert_trip_info is flat.
333  std::cout << "ERROR: Failed to convert info to string?!\n";
334  }
335  }
336 
338 
339 } // fc
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::assert_optional
bool assert_optional(bool is_valid)
Definition: exception.cpp:290
fc::unhandled_exception::dynamic_rethrow_exception
virtual void dynamic_rethrow_exception() const
Definition: exception.cpp:99
fc::exception
Used to generate a useful error report when an exception is thrown.
Definition: exception.hpp:56
fc::mutable_variant_object
An order-perserving dictionary of variant's.
Definition: variant_object.hpp:108
fc::unhandled_exception::unhandled_exception
unhandled_exception(log_message &&m, std::exception_ptr e=std::current_exception())
Definition: exception.cpp:84
fc::unhandled_exception::get_inner_exception
std::exception_ptr get_inner_exception() const
Definition: exception.cpp:97
fc::exception::get_log
const log_messages & get_log() const
Definition: exception.cpp:172
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::variant::as_string
std::string as_string() const
Definition: variant.cpp:469
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::from_variant
void from_variant(const variant &var, flat_set< T, A... > &vo, uint32_t _max_depth)
Definition: flat.hpp:116
fc::exception_ptr
std::shared_ptr< exception > exception_ptr
Definition: exception.hpp:131
fc::json::to_string
static string to_string(const variant &v, output_formatting format=stringify_large_ints_and_doubles, uint32_t max_depth=DEFAULT_MAX_RECURSION_DEPTH)
Definition: json.cpp:650
fc::invalid_operation_exception_code
@ invalid_operation_exception_code
Definition: exception.hpp:32
fc::cout
cout_t & cout
Definition: iostream.cpp:175
FC_REGISTER_EXCEPTIONS
#define FC_REGISTER_EXCEPTIONS(SEQ)
Definition: exception.hpp:218
fc::null_optional_code
@ null_optional_code
Definition: exception.hpp:34
fc::throw_assertion_failure
void throw_assertion_failure(const std::string &message)
Definition: exception.cpp:308
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
sstream.hpp
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::to_variant
void to_variant(const flat_set< T, A... > &var, variant &vo, uint32_t _max_depth)
Definition: flat.hpp:105
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::format_string
std::string format_string(const std::string &, const variant_object &, uint32_t max_object_depth=200)
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
json.hpp
FC_ASSERT
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
Definition: exception.hpp:345
fc::log_message
aggregates a message along with the context and associated meta-information.
Definition: log_message.hpp:106
fc::variant::get_object
variant_object & get_object()
Definition: variant.cpp:554
fc::variant
stores null, int64, uint64, double, bool, string, std::vector<variant>, and variant_object's.
Definition: variant.hpp:198
exception.hpp
Defines exception's used by fc.
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::canceled_exception_code
@ canceled_exception_code
Definition: exception.hpp:28
logger.hpp
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::log_level
Definition: log_message.hpp:23
fc::exception_factory::rethrow
void rethrow(const exception &e) const
Definition: exception.cpp:250
fc::FC_IMPLEMENT_EXCEPTION
FC_IMPLEMENT_EXCEPTION(method_not_found_exception, method_not_found_exception_code, "Method Not Found")
fc::except_str
std::string except_str()
Definition: exception.cpp:272
fc::timeout_exception_code
@ timeout_exception_code
timeout exceptions
Definition: exception.hpp:21
fc::exception::operator=
exception & operator=(const exception &copy)
Definition: exception.cpp:296
FC_THROW_EXCEPTION
#define FC_THROW_EXCEPTION(EXCEPTION, FORMAT,...)
Definition: exception.hpp:379
fc::out_of_range_exception_code
@ out_of_range_exception_code
Definition: exception.hpp:27
fc::throw_bad_enum_cast
void throw_bad_enum_cast(int64_t i, const char *e)
Definition: exception.cpp:277
fc::unhandled_exception::dynamic_copy_exception
virtual std::shared_ptr< exception > dynamic_copy_exception() const
Definition: exception.cpp:105