FastJet  3.3.3
Error.cc
1 //FJSTARTHEADER
2 // $Id: Error.cc 4420 2019-11-29 09:28:20Z soyez $
3 //
4 // Copyright (c) 2005-2019, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
5 //
6 //----------------------------------------------------------------------
7 // This file is part of FastJet.
8 //
9 // FastJet is free software; you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation; either version 2 of the License, or
12 // (at your option) any later version.
13 //
14 // The algorithms that underlie FastJet have required considerable
15 // development. They are described in the original FastJet paper,
16 // hep-ph/0512210 and in the manual, arXiv:1111.6097. If you use
17 // FastJet as part of work towards a scientific publication, please
18 // quote the version you use and include a citation to the manual and
19 // optionally also to hep-ph/0512210.
20 //
21 // FastJet is distributed in the hope that it will be useful,
22 // but WITHOUT ANY WARRANTY; without even the implied warranty of
23 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 // GNU General Public License for more details.
25 //
26 // You should have received a copy of the GNU General Public License
27 // along with FastJet. If not, see <http://www.gnu.org/licenses/>.
28 //----------------------------------------------------------------------
29 //FJENDHEADER
30 
31 #include "fastjet/Error.hh"
32 #include "fastjet/config.h"
33 #include <sstream>
34 
35 #ifndef __FJCORE__
36 // printing the stack would need execinfo
37 #ifdef FASTJET_HAVE_EXECINFO_H
38 #include <execinfo.h>
39 #include <cstdlib>
40 #ifdef FASTJET_HAVE_DEMANGLING_SUPPORT
41 #include <cstdio>
42 #include <cxxabi.h>
43 #endif // FASTJET_HAVE_DEMANGLING_SUPPORT
44 #endif // FASTJET_HAVE_EXECINFO_H
45 #endif // __FJCORE__
46 
47 FASTJET_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh
48 
49 using namespace std;
50 
51 bool Error::_print_errors = true;
52 bool Error::_print_backtrace = false;
53 ostream * Error::_default_ostr = & cerr;
54 #if (!defined(FASTJET_HAVE_EXECINFO_H)) || defined(__FJCORE__)
55  LimitedWarning Error::_execinfo_undefined;
56 #endif
57 
58 //----------------------------------------------------------------------
59 #ifndef __FJCORE__
60 
61 // demangling only is included, i.e. --enable-demangling is specified
62 // at configure time, execinfo.h is present and the GNU C++ ABI is
63 // supported
64 #if defined(FASTJET_HAVE_EXECINFO_H) && defined(FASTJET_HAVE_DEMANGLING_SUPPORT)
65 // demangle a given backtrace symbol
66 //
67 // Notes:
68 // - at the moment, only the symbol is parsed.
69 // - one can get the offset by using
70 // "%*[^(]%*[^_]%127[^+)]%64[+x0123456789abcdef]", symbol, offset
71 // and checking if sscanf returns 0, 1 or 2
72 // (offset includes the leading +)
73 // - Similarly one could exctract the address and try to convert it
74 // into a filename+line number like addr2line does but this seems
75 // to require exteral dependencies. If we want to go down that
76 // route, one could look into the inplementation o faddr2line(.c)
77 // and/or dladdr.
78 string Error::_demangle(const char* symbol) {
79  size_t size;
80  int status;
81  char temp[128];
82  char* demangled;
83  // first, try to demangle a c++ name
84  // decryption:
85  // %*[^(] matches any number of characters different from "("
86  // the * tells not to store in input var
87  // %*[^_] matches any number of characters different from "_"
88  // the * tells not to store in input var
89  // %127[^)+] matches at most 127 characters different from "+"
90  // match is stored
91  if (1 == sscanf(symbol, "%*[^(]%*[^_]%127[^)+]", temp)) {
92  //cout << symbol << " -> " << temp << endl;
93  if (NULL != (demangled = abi::__cxa_demangle(temp, NULL, &size, &status))) {
94  string result(demangled);
95  free(demangled);
96  return result;
97  }
98  }
99  //if that didn't work, try to get a regular c symbol
100  if (1 == sscanf(symbol, "%127s", temp)) {
101  return temp;
102  }
103 
104  //if all else fails, just return the symbol
105  return symbol;
106 }
107 #endif // FASTJET_HAVE_DEMANGLING_SUPPORT && FASTJET_HAVE_EXECINFO_H
108 #endif // __FJCORE__
109 
110 
111 //----------------------------------------------------------------------
112 Error::Error(const std::string & message_in) {
113  _message = message_in;
114 
115  if (_print_errors && _default_ostr){
116  ostringstream oss;
117  oss << "fastjet::Error: "<< message_in << endl;
118 
119 #ifndef __FJCORE__
120  // only print the stack if execinfo is available and stack enabled
121 #ifdef FASTJET_HAVE_EXECINFO_H
122  if (_print_backtrace){
123  void * array[10];
124  char ** messages;
125 
126  int size = backtrace(array, 10);
127  messages = backtrace_symbols(array, size);
128 
129  oss << "stack:" << endl;
130  for (int i = 1; i < size && messages != NULL; ++i){
131 #ifdef FASTJET_HAVE_DEMANGLING_SUPPORT
132  oss << " #" << i << ": " << _demangle(messages[i])
133  << " [" << messages[i] << "]" << endl;
134 #else
135  oss << " #" << i << ": " << messages[i] << endl;
136 #endif
137  }
138  free(messages);
139  }
140 #endif // FASTJET_HAVE_EXECINFO_H
141 #endif // __FJCORE__
142 
143  *_default_ostr << oss.str();
144  // get something written to file even
145  // if the program aborts
146  _default_ostr->flush();
147 
148  // // output error message either to cerr or to the user-set stream
149  // if (_default_ostr) { *_default_ostr << oss.str();
150  // // get something written to file even
151  // // if the program aborts
152  // _default_ostr->flush(); }
153  // else { std::cerr << oss.str(); }
154 
155  }
156 }
157 
158 //----------------------------------------------------------------------
159 void Error::set_print_backtrace(bool enabled) {
160 #if (!defined(FASTJET_HAVE_EXECINFO_H)) || defined(__FJCORE__)
161  if (enabled) {
162  _execinfo_undefined.warn("Error::set_print_backtrace(true) will not work with this build of FastJet");
163  }
164 #endif
165  _print_backtrace = enabled;
166 }
167 
168 FASTJET_END_NAMESPACE
169