Lumiera  0.pre.03
»edityourfreedom«
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
error-exception.cpp
Go to the documentation of this file.
1 /*
2  ERROR-EXCEPTION - Lumiera exception classes
3 
4  Copyright (C) Lumiera.org
5  2008, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 * *****************************************************/
22 
23 
35 #include "lib/error.hpp"
36 #include "lib/meta/util.hpp"
37 #include "lib/util.hpp"
38 
39 #include <exception>
40 #include <typeinfo>
41 #include <iostream>
42 
43 using util::cStr;
44 using util::isnil;
45 using std::exception;
46 
47 
48 namespace lumiera {
49  namespace error {
50 
57  inline const string
58  default_usermsg (Error*) noexcept
59  {
60  return "Sorry, Lumiera encountered an internal error.";
61  }
62 
63  CStr
65  {
66  CStr detailinfo = lumiera_error_extra();
67  return isnil (detailinfo)? "Lumiera errorstate detected"
68  : detailinfo;
69  }
70 
71 
72  /* constants to be used as error IDs */
73  LUMIERA_ERROR_DEFINE (LOGIC , "internal logic broken");
74  LUMIERA_ERROR_DEFINE (FATAL , "floundered");
75  LUMIERA_ERROR_DEFINE (CONFIG , "misconfiguration");
76  LUMIERA_ERROR_DEFINE (STATE , "unforeseen state");
77  LUMIERA_ERROR_DEFINE (FLAG , "non-cleared lumiera errorstate");
78  LUMIERA_ERROR_DEFINE (INVALID , "invalid input or parameters");
79  LUMIERA_ERROR_DEFINE (EXTERNAL , "failure in external service");
80  LUMIERA_ERROR_DEFINE (ASSERTION, "assertion failure");
81 
82  /* some further generic error situations */
83  LUMIERA_ERROR_DEFINE (LIFECYCLE, "Lifecycle assumptions violated");
84  LUMIERA_ERROR_DEFINE (WRONG_TYPE, "runtime type mismatch");
85  LUMIERA_ERROR_DEFINE (ITER_EXHAUST, "end of sequence reached");
86  LUMIERA_ERROR_DEFINE (CAPACITY, "predefined fixed storage capacity");
87  LUMIERA_ERROR_DEFINE (INDEX_BOUNDS, "index out of bounds");
88  LUMIERA_ERROR_DEFINE (BOTTOM_VALUE, "invalid or NIL value");
89  LUMIERA_ERROR_DEFINE (UNCONNECTED, "missing connection");
90  LUMIERA_ERROR_DEFINE (UNIMPLEMENTED,"using a feature not yet implemented....");
91 
92  } // namespace error
93 
94  LUMIERA_ERROR_DEFINE (EXCEPTION, "generic Lumiera exception");
95 
96 
97 
98 
100  Error::Error (string description, lumiera_err const id) noexcept
101  : std::exception{}
102  , id_{id}
103  , msg_{error::default_usermsg (this)}
104  , desc_{description}
105  , cause_{}
106  {
107  lumiera_error_set (this->id_, description.c_str());
108  }
109 
110 
111  Error::Error (std::exception const& cause,
112  string description, lumiera_err const id) noexcept
113  : std::exception{}
114  , id_{id}
115  , msg_{error::default_usermsg (this)}
116  , desc_{description}
117  , cause_{extractCauseMsg(cause)}
118  {
119  lumiera_error_set (this->id_, description.c_str());
120  }
121 
122 
123 
124 
130  CStr
131  Error::what() const noexcept
132  {
133  if (isnil (this->what_))
134  {
135  what_ = string(id_);
136  if (!isnil (desc_)) what_ += " ("+desc_+").";
137  if (!isnil (cause_)) what_ += string(" -- caused by: ") + cause_;
138  }
139  return what_.c_str();
140  }
141 
142 
146  const string
147  Error::extractCauseMsg (const exception& cause) noexcept
148  {
149  const Error* err = dynamic_cast<const Error*> (&cause);
150  if (err)
151  {
152  if (isnil (err->cause_))
153  return cause.what(); // cause is root cause
154  else
155  return err->cause_; // cause was caused by another exception
156  }
157  // unknown other exception type
158  return cause.what ();
159  }
160 
161 
162 
163 
164 
165 
166 
167  namespace error {
168  namespace {
170  {
171  std::set_terminate (lumiera_unexpectedException);
172  }
173  LifecycleHook schedule_ (ON_BASIC_INIT, &install_unexpectedException_handler);
174 
175  std::terminate_handler nextHandler = nullptr;
176  }
177 
178 
180  {
181  CStr is_halted
182  = "### Lumiera halted due to an unexpected Error ###";
183 
184  ERROR (NOBUG_ON, "%s", is_halted);
185  std::cerr << "\n" << is_halted << "\n\n";
186 
187 
188  try { // -----find-out-about-any-Exceptions--------
189  auto lastException = std::current_exception();
190  if (lastException) {
191  std::rethrow_exception (lastException);
192  }
193  } catch(const lumiera::Error& lerr) {
194  std::cout << "\n+++ Caught Exception " << lerr.getID() << "\n\n";
195  ERROR (NOBUG_ON, "+++ caught %s\n+++ messg: %s\n+++ descr: %s"
196  , cStr(util::typeStr(lerr))
197  , cStr(lerr.getUsermsg())
198  , cStr(lerr.what())
199  );
200  if (not isnil(lerr.rootCause()))
201  ERROR (NOBUG_ON, "+++ cause: %s",cStr(lerr.rootCause()));
202 
203  } catch(const std::exception& e) {
204  ERROR (NOBUG_ON, "Generic Exception: %s", e.what());
205  std::cout << "+++ Caught Exception \"" << e.what() << "\"\n";
206  } catch(...) {
207  ERROR (NOBUG_ON, "FATAL -- unknown exception");
208  }
209 
210  if (CStr errorstate = lumiera_error ())
211  ERROR (NOBUG_ON, "last registered error was....\n%s", errorstate);
212 
213  if (nextHandler)
214  nextHandler();
215  else
216  std::abort();
217  }
218 
219 
220  void assertion_terminate (const string& location)
221  {
222  throw Fatal (location, LUMIERA_ERROR_ASSERTION)
223  .setUsermsg("Program terminated because of violating "
224  "an internal consistency check.");
225  }
226 
227  } // namespace error
228 
229 } // namespace lumiera
const char * ON_BASIC_INIT
automatic static init. treated specially to run as soon as possible
void assertion_terminate(const string &location)
throw an error::Fatal indicating "assertion failure"
lumiera_err getID() const noexcept
the internal Lumiera-error-ID (was set as C-errorstate in ctor)
Definition: error.hpp:101
LUMIERA_ERROR_DEFINE(LOGIC,"internal logic broken")
string desc_
detailed description of the error situation for the developers
Definition: error.hpp:74
const char * CStr
Definition: error.hpp:55
Simple and lightweight helpers for metaprogramming and type detection.
const string default_usermsg(Error *) noexcept
the message shown to the user per default if an exception reaches one of the top-level catch clauses...
void install_unexpectedException_handler()
install our own handler for undeclared exceptions.
Error(string description="", lumiera_err const id=LERR_(EXCEPTION)) noexcept
this is an interface
std::string typeStr(TY const *obj=nullptr) noexcept
failsafe human readable type display
Definition: meta/util.hpp:272
const char * cStr(string const &org)
convenience shortcut: conversion to c-String via string.
Definition: util.hpp:380
void lumiera_unexpectedException() noexcept
global function for handling unknown exceptions encountered at functions declaring not to throw this ...
lumiera_err const id_
an LUMIERA_ERROR id, which is set as errorstate on construction
Definition: error.hpp:72
static const string extractCauseMsg(std::exception const &) noexcept
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
lumiera_err lumiera_error(void)
Get and clear current error state.
Definition: error-state.c:124
LUMIERA_ERROR_DEFINE(EXCEPTION,"generic Lumiera exception")
const char * lumiera_err
Definition: error.h:57
string const & getUsermsg() const noexcept
extract the message to be displayed for the user
Definition: error.hpp:108
string const & rootCause() const noexcept
If this exception was caused by a chain of further exceptions, return the description of the first on...
Definition: error.hpp:120
bool isnil(lib::time::Duration const &dur)
Definition: timevalue.hpp:642
const string cause_
description of first exception encountered in the chain
Definition: error.hpp:76
Lumiera error handling (C++ interface).
lumiera_err lumiera_error_set(lumiera_err nerr, const char *extra)
Set error state for the current thread.
Definition: error-state.c:105
string what_
buffer for generating the detailed description on demand
Definition: error.hpp:75
virtual CStr what() const noexceptoverride
std::exception interface : yield a diagnostic message
Lumiera public interface.
const char * lumiera_error_extra(void)
Query the extra context for the last error.
Definition: error-state.c:135
Interface and Base definition for all Lumiera Exceptions.
Definition: error.hpp:69
LumieraError< LERR_(FATAL), Logic > Fatal
Definition: error.hpp:213