lsst.cpputils
g87389fa792+0bb42a27e1
Toggle main menu visibility
Loading...
Searching...
No Matches
src
Backtrace.cc
Go to the documentation of this file.
1
// -*- lsst-c++ -*-
2
3
/*
4
* LSST Data Management System
5
* Copyright 2008-2017 AURA/LSST.
6
*
7
* This product includes software developed by the
8
* LSST Project (http://www.lsst.org/).
9
*
10
* This program is free software: you can redistribute it and/or modify
11
* it under the terms of the GNU General Public License as published by
12
* the Free Software Foundation, either version 3 of the License, or
13
* (at your option) any later version.
14
*
15
* This program is distributed in the hope that it will be useful,
16
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
* GNU General Public License for more details.
19
*
20
* You should have received a copy of the LSST License Statement and
21
* the GNU General Public License along with this program. If not,
22
* see <https://www.lsstcorp.org/LegalNotices/>.
23
*/
24
25
#if defined(LSST_CPPUTILS_BACKTRACE_ENABLE) && (defined(__clang__) || defined(__GNUC__))
26
27
#include <cerrno>
28
#include <cstdio>
29
#include <cstdlib>
30
#include <csignal>
31
32
#include <cxxabi.h>
33
#include <execinfo.h>
34
35
#include <regex>
36
37
#include "
lsst/cpputils/Backtrace.h
"
38
39
namespace
lsst
{
40
namespace
cpputils
{
41
42
namespace
{
43
45
static
constexpr
size_t
MAX_FRAMES = 128;
47
static
constexpr
size_t
NAME_SIZE_ESTIMATE = 1024;
48
61
char
*demangleAndPrint(
char
*input,
char
*buffer,
size_t
*bufferSize)
noexcept
{
62
int
status = 1;
63
64
try
{
65
std::cmatch matches;
66
std::regex rgx(
67
"(.*[\\s|\\(])"
// before
68
"(_\\w+)"
// mangled name
69
"(.*\\+.*)"
// after
70
);
71
72
if
(
std::regex_match
(input, matches, rgx)) {
73
buffer = abi::__cxa_demangle(matches.
str
(2).c_str(), buffer, bufferSize, &status);
74
fprintf
(stderr,
"%s%s%s\n"
, matches.
str
(1).c_str(), buffer, matches.
str
(3).c_str());
75
}
76
}
catch
(
const
std::regex_error &e) {
77
fprintf
(stderr,
"[demangleAndPrint] %s\n"
, e.
what
());
78
status = 1;
79
}
catch
(
const
std::runtime_error &e) {
80
fprintf
(stderr,
"[demangleAndPrint] %s\n"
, e.
what
());
81
status = 1;
82
}
catch
(
const
std::exception &e) {
83
fprintf
(stderr,
"[demangleAndPrint] %s\n"
, e.
what
());
84
status = 1;
85
}
catch
(...) {
86
fprintf
(stderr,
"[demangleAndPrint] unknown error occurred in demangling\n"
);
87
status = 1;
88
}
89
90
if
(status != 0) {
91
// no name found to demangle or name demangling failed
92
fprintf
(stderr,
"%s\n"
, input);
93
}
94
return
buffer;
95
}
96
104
void
raiseWithDefaultHandler(
int
signum)
noexcept
{
105
signal
(signum, SIG_DFL);
106
raise
(signum);
107
}
108
114
void
signalHandler(
int
signum)
noexcept
{
115
fprintf
(stderr,
"Caught signal %d, backtrace follows:\n"
, signum);
116
117
// retrieve current stack addresses
118
void
*addressList[MAX_FRAMES + 1];
119
size_t
addressLength =
backtrace
(addressList, MAX_FRAMES);
120
if
(addressLength == 0) {
121
fprintf
(stderr,
" \n"
);
122
return
;
123
}
124
125
// translate the addresses into an array of strings
126
// that describe the addresses symbolically.
127
// return value symbolList is malloc'ed and must be free'd
128
char
**symbolList = backtrace_symbols(addressList, addressLength);
129
if
(symbolList == NULL) {
130
fprintf
(stderr,
"[backtrace_symbols] cannot dump trace, probably out of memory\n"
);
131
raiseWithDefaultHandler(signum);
132
}
133
134
// allocate storage for demangled name
135
// this will be reallocated by abi::__cxa_demangle in demangleAndPrint
136
// if storage is insufficient, but if it is sufficient
137
// this reduces the number of allocations
138
size_t
nameSize = NAME_SIZE_ESTIMATE;
139
char
*name = (
char
*)
malloc
(nameSize *
sizeof
(
char
));
140
if
(name == NULL) {
141
fprintf
(stderr,
"[malloc] cannot dump trace, probably out of memory\n"
);
142
raiseWithDefaultHandler(signum);
143
}
144
145
for
(
size_t
i = 0; i < addressLength; ++i) {
146
if
(
char
*buffer = demangleAndPrint(symbolList[i], name, &nameSize)) {
147
// buffer may have been realloc'ed
148
name = buffer;
149
}
150
}
151
152
free
(name);
153
free
(symbolList);
154
raiseWithDefaultHandler(signum);
155
}
156
157
}
// namespace
158
159
Backtrace::Backtrace
() noexcept : enabled(true) {
160
// Register abort handlers
161
signal
(SIGABRT, signalHandler);
162
signal
(SIGSEGV, signalHandler);
163
signal
(SIGILL, signalHandler);
164
signal
(SIGFPE, signalHandler);
165
}
166
167
}
// namespace cpputils
168
}
// namespace lsst
169
170
#else
171
172
#include "
lsst/cpputils/Backtrace.h
"
173
174
namespace
lsst
{
175
namespace
cpputils
{
176
177
Backtrace::Backtrace
() noexcept : enabled(false) {}
178
179
}
// namespace cpputils
180
}
// namespace lsst
181
182
#endif
Backtrace.h
lsst::cpputils::Backtrace::Backtrace
Backtrace(Backtrace const &)=delete
std::fprintf
T fprintf(T... args)
std::free
T free(T... args)
std::malloc
T malloc(T... args)
lsst::cpputils.backtrace
Definition
__init__.py:1
lsst::cpputils
Definition
main.dox:1
lsst
std::raise
T raise(T... args)
std::regex_match
T regex_match(T... args)
std::signal
T signal(T... args)
std::cmatch::str
T str(T... args)
std::regex_error::what
T what(T... args)
Generated on
for lsst.cpputils by
1.17.0