Exception.cpp
Go to the documentation of this file.
1/*
2* This file is part of ArmarX.
3*
4* Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5*
6* ArmarX is free software; you can redistribute it and/or modify
7* it under the terms of the GNU General Public License version 2 as
8* published by the Free Software Foundation.
9*
10* ArmarX is distributed in the hope that it will be useful, but
11* WITHOUT ANY WARRANTY; without even the implied warranty of
12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13* GNU General Public License for more details.
14*
15* You should have received a copy of the GNU General Public License
16* along with this program. If not, see <http://www.gnu.org/licenses/>.
17*
18* @package ArmarXCore::core
19* @author Jan Issac (jan dot issac at gmx dot de)
20* @author Kai Welke (welke at kit dot edu)
21* @date 2011
22* @copyright http://www.gnu.org/licenses/gpl-2.0.txt
23* GNU General Public License
24*/
25
26#include "Exception.h"
27
28#include <cstdio>
29#include <cstdlib>
30#include <sstream>
31
32#include <dlfcn.h>
33
34#include <Ice/LocalException.h>
35#include <IceUtil/Exception.h>
36
40
41#include <cxxabi.h>
42#include <execinfo.h>
43
44namespace armarx
45{
46 LocalException::LocalException() : reason(""), backtrace(""), output_buffer("")
47 {
48 backtrace = std::runtime_error(generateBacktrace());
49 setReason("");
50 }
51
52 LocalException::LocalException(const LocalException& e) noexcept :
53 reason(e.reason), backtrace(e.backtrace), output_buffer("")
54 {
55 }
56
57 void
58 LocalException::setReason(const std::string& r)
59 {
60 this->reason = std::runtime_error(r);
61 }
62
63 std::string
64 LocalException::getReason() const
65 {
66 return reason.what();
67 }
68
69 const char*
70 LocalException::what() const noexcept
71 {
72 // TODO: generateOutputString is not noexcept and changes the state of the exception
73 output_buffer = std::runtime_error(generateOutputString());
74
75 return output_buffer.what();
76 }
77
78 std::string
79 LocalException::generateBacktrace()
80 {
81 int skip = 3;
82 void* callstack[128];
83 const int nMaxFrames = sizeof(callstack) / sizeof(callstack[0]);
84 char buf[1024];
85
86 int nFrames = ::backtrace(callstack, nMaxFrames);
87 char** symbols = backtrace_symbols(callstack, nFrames);
88
89 std::ostringstream trace_buf;
90
91 for (int i = skip; i < nFrames; i++)
92 {
93 Dl_info info;
94
95 if (dladdr(callstack[i], &info) && info.dli_sname)
96 {
97 char* demangled = nullptr;
98 int status = -1;
99
100 if (info.dli_sname[0] == '_')
101 {
102 demangled = abi::__cxa_demangle(info.dli_sname, nullptr, nullptr, &status);
103 }
104
105 snprintf(buf,
106 sizeof(buf),
107 "%-3d %*p %s + %zd\n",
108 i - skip + 1,
109 int(2 + sizeof(void*) * 2),
110 callstack[i],
111 status == 0 ? demangled
112 : info.dli_sname == nullptr ? symbols[i]
113 : info.dli_sname,
114 (char*)callstack[i] - (char*)info.dli_saddr);
115 free(demangled);
116 }
117 else
118 {
119 snprintf(buf,
120 sizeof(buf),
121 "%-3d %*p %s\n",
122 i - skip + 1,
123 int(2 + sizeof(void*) * 2),
124 callstack[i],
125 symbols[i]);
126 }
127
128 trace_buf << buf;
129 }
130
131 free(symbols);
132
133 if (nFrames == nMaxFrames)
134 {
135 trace_buf << "[truncated]\n";
136 }
137
138 return trace_buf.str();
139 }
140
141 std::string
142 LocalException::generateOutputString() const
143 {
144 // TODO: this is not noexcept
145 std::stringstream what_buf;
146
147 what_buf << std::endl;
148 what_buf << "Reason: " << ((strlen(reason.what()) == 0) ? "undefined" : reason.what())
149 << std::endl;
150 what_buf << "Backtrace: " << std::endl;
151 what_buf << backtrace.what() << std::endl;
152
153 return what_buf.str();
154 }
155
156 void
163
164 std::string
166 {
167 std::stringstream result;
168
169 try
170 {
171 throw;
172 }
173 catch (const UserException& userException)
174 {
175 // Handle marshallable user exceptions
176 result << "Caught userException: " << userException.what() << "\n"
177 << "\tReason: " << userException.reason << "\n"
178 << "\tStacktrace: \n"
179 << userException.ice_stackTrace();
180 }
181
182
183 catch (const LocalException& exception)
184 {
185 // Handle local (run-time) exceptions
186 result << "Caught " << exception.name() << ":\n" << exception.what();
187 }
188
189 catch (const Ice::NoValueFactoryException& e)
190 {
191 std::stringstream availableFactories;
192
194 {
195 ObjectFactoryMap objFacMap = elem->getFactories();
196 ObjectFactoryMap::iterator it = objFacMap.begin();
197
198 for (; it != objFacMap.end(); it++)
199 {
200 availableFactories << "\t" << it->first;
201 availableFactories << "\n";
202 }
203 }
204
205 auto typePart = e.type.substr(e.type.find_last_of(':') + 1);
206
207 result
208 << "Caught NoObjectFactoryException:\n " << e.what() << "\n\nPossible reasons:\n"
209 << "\t- You did not link the library where the object factory is declared\n"
210 << "\t- You did not include the header of the object factory\n\n"
211 << "\tThese object factories are usually located in header files called "
212 "XYZObjectFactories.h. This header file needs to be included into your library."
213 << "Additionally, also the library needs to be included. To find these file you "
214 "can try the following command (linux):\n"
215 << "\tgrep -r \"" << typePart << "\" ~/armarx/ --include \"*Factor*\"\n"
216 << "\t Include that header file and find out to which libray this header belongs "
217 "(usually the CMakeLists.txt next to it) and link this lib to your library."
218 << "\n\nAvailable factories: \n"
219 << availableFactories.str()
220 // << "\nBacktrace: " << exception.ice_stackTrace()
221 ;
222 }
223 catch (const Ice::UnexpectedObjectException& e)
224 {
225 std::stringstream availableFactories;
226
228 {
229 ObjectFactoryMap objFacMap = elem->getFactories();
230 ObjectFactoryMap::iterator it = objFacMap.begin();
231
232 for (; it != objFacMap.end(); it++)
233 {
234 availableFactories << "\t" << it->first;
235 availableFactories << "\n";
236 }
237 }
238
239 auto typePart = e.expectedType.substr(e.expectedType.find_last_of(':') + 1);
240
241 result
242 << "Caught UnexpectedObjectException:\n " << e.what() << "\n\nPossible reasons:\n"
243 << "\t- You did not link the library where the object factory is declared\n"
244 << "\t- You did not include the header of the object factory\n\n"
245 << "\tThese object factories are usually located in header files called "
246 "XYZObjectFactories.h. This header file needs to be included into your library."
247 << "Additionally, also the library needs to be included. To find these file you "
248 "can try the following command (linux):\n"
249 << "\tgrep -r \"" << typePart << "\" ~/armarx/ --include \"*Factor*\"\n"
250 << "\t Include that header file and find out to which libray this header belongs "
251 "(usually the CMakeLists.txt next to it) and link this lib to your library."
252 << "\n\nAvailable factories: \n"
253 << availableFactories.str()
254 // << "\nBacktrace: " << exception.ice_stackTrace()
255 ;
256 }
257
258 catch (const Ice::OperationNotExistException& e)
259 {
260 result << "\033[1mCaught OperationNotExistException:\n " << e.what()
261 << "\n\nPossible reasons:\n"
262 << "\t- You are using a topic instead of offering a topic (usingTopic(name): "
263 "receive data, offeringTopic(name): provide data) \n"
265 }
266
267 catch (const IceUtil::Exception& exception)
268 {
269
270 result << "Caught IceUtil::Exception:\n " << exception.what()
271 << "\nBacktrace: " << exception.ice_stackTrace();
272 }
273 catch (const std::exception& exception)
274 {
275
276 result << "Caught std::exception:\n" << exception.what();
277 }
278 catch (...)
279 {
280 result << "Caught unknown exception!";
281 }
282 result << "\nTrace created by calling ARMARX_TRACE:\n";
284 return result.str();
285 }
286} // namespace armarx
static const std::vector< FactoryCollectionBasePtr > & GetPreregistratedFactories()
static std::string GetColorCodeString(MessageTypeT verbosityLevel)
#define ARMARX_LOG_S
This macro creates a new temporary instance which can then be used to log data using the << operator.
Definition Logging.h:143
This file offers overloads of toIce() and fromIce() functions for STL container types.
std::map< std::string, Ice::ValueFactoryPtr > ObjectFactoryMap
std::string GetHandledExceptionString()
void handleExceptions()
static void PrintExceptionBacktrace(std::ostream &out, const std::string &pre="")
Definition trace.cpp:216
static void ClearExceptionBacktrace()
Definition trace.cpp:100