Anklang 0.3.0-460-gc4ef46ba
ASE — Anklang Sound Engine (C++)

« « « Anklang Documentation
Loading...
Searching...
No Matches
cxxaux.cc
Go to the documentation of this file.
1 // This Source Code Form is licensed MPL-2.0: http://mozilla.org/MPL/2.0
2#include "cxxaux.hh"
3#include <cxxabi.h> // abi::__cxa_demangle
4#include <unistd.h>
5#include <fcntl.h>
6#include <cstring>
7
8namespace Ase {
9
10VirtualBase::~VirtualBase() noexcept
11{}
12
17const char*
18string_demangle_cxx (const char *mangled_identifier) noexcept
19{
20 static auto &m2d = *new std::unordered_map<const char*, const char*>();
21 static std::mutex mtx;
22 { std::lock_guard<std::mutex> locker (mtx);
23 auto it = m2d.find (mangled_identifier);
24 if (it != m2d.end())
25 return it->second;
26 }
27 int status = 0;
28 char *malloced_result = abi::__cxa_demangle (mangled_identifier, NULL, NULL, &status);
29 if (malloced_result && !status) {
30 std::lock_guard<std::mutex> locker (mtx);
31 auto it = m2d.find (mangled_identifier);
32 if (it != m2d.end()) {
33 free (malloced_result);
34 return it->second;
35 }
36 m2d[mangled_identifier] = malloced_result;
37 return malloced_result;
38 }
39 return mangled_identifier;
40}
41
45{
46 bool allow_ptrace = true;
47#if 0 && defined (__linux__)
48 // disabling this check, so the debugger can showman appropriate error message
49 const char *const ptrace_scope = "/proc/sys/kernel/yama/ptrace_scope";
50 int fd = open (ptrace_scope, 0);
51 char b[8] = { 0 };
52 if (read (fd, b, 8) > 0)
53 allow_ptrace = b[0] == '0';
54 close (fd);
55#endif
56 if (!allow_ptrace)
57 return "";
58 char cmd[3192];
59 const char *const usr_bin_lldb = "/usr/bin/lldb";
60 if (access (usr_bin_lldb, X_OK) == 0) {
61 snprintf (cmd, sizeof (cmd),
62 "%s -Q -x --batch -p %u "
63 "-o 'bt all'",
64 usr_bin_lldb, gettid());
65 return cmd;
66 }
67 const char *const usr_bin_gdb = "/usr/bin/gdb";
68 if (access (usr_bin_gdb, X_OK) == 0) {
69 snprintf (cmd, sizeof (cmd),
70 "%s -q -n --nx -p %u --batch "
71 "-iex 'set auto-load python-scripts off' "
72 "-iex 'set script-extension off' "
73 "-ex 'set print address off' "
74 // "-ex 'set print frame-arguments none' "
75 "-ex 'thread apply all backtrace 99' " // max frames
76 ">&2 2>/dev/null",
77 usr_bin_gdb, gettid());
78 return cmd;
79 }
80 return "";
81}
82
84static bool
85has_debug_key (const char *const debugkeys, const char *const key)
86{
87 if (!debugkeys) return false;
88 const auto l = strlen (key);
89 const auto d = strstr (debugkeys, key);
90 return d && (d == debugkeys || d[-1] == ':') && (d[l] == 0 || d[l] == ':');
91}
92
93void
94perror_die (const std::string &msg) noexcept
95{
97 std::string message = msg;
98 if (errno)
99 message += std::string (": ") + strerror (errno);
100 assertion_failed (message.c_str(), nullptr, 0, nullptr);
101 for (;;)
102 abort();
103}
104
107
109void
110assertion_fatal (const char *msg, const char *file, int line, const char *func) noexcept
111{
113 assertion_failed (msg, file, line, func);
114 for (;;)
115 abort();
116}
117
118static void assertion_abort (const char *msg, const char *file, int line, const char *func) noexcept ASE_NORETURN;
119
121void
122assertion_failed (const char *msg, const char *file, int line, const char *func) noexcept
123{
124 std::string m;
125 if (file && line > 0 && func)
126 m += std::string (file) + ":" + std::to_string (unsigned (line)) + ":" + func + ": ";
127 else if (file && line > 0)
128 m += std::string (file) + ":" + std::to_string (unsigned (line)) + ": ";
129 else if (file || func)
130 m += std::string (file ? file : func) + ": ";
131 if (!msg || !msg[0])
132 m += "assertion unreachable\n";
133 else {
134 if (line >= 0)
135 m += "assertion failed: ";
136 m += msg;
137 if (!m.empty() && m.back() != '\n')
138 m += "\n";
139 }
140 fflush (stdout); // preserve output ordering
141 fputs (m.c_str(), stderr);
142 fflush (stderr); // some platforms (_WIN32) don't properly flush on '\n'
143 const char *const d = getenv ("ASE_DEBUG");
144 if (!assertion_failed_fatal && has_debug_key (d, "fatal-warnings"))
146 if (assertion_failed_fatal || has_debug_key (d, "breakpoint")) {
147#if (defined __i386__ || defined __x86_64__)
148 __asm__ __volatile__ ("int $03");
149#else
150 __builtin_trap();
151#endif
152 } else if (has_debug_key (d, "backtrace")) {
153 const std::string gdb_cmd = backtrace_command();
154 if (!gdb_cmd.empty()) {
155 const auto res = system (gdb_cmd.c_str());
156 (void) res;
157 }
158 }
160 assertion_abort (msg, file, line, func);
161}
162
163} // Ase
164
165#undef NDEBUG // enable __GLIBC__ __assert_fail()
166#include <cassert>
167namespace Ase {
168static void
169assertion_abort (const char *msg, const char *file, int line, const char *func) noexcept
170{
171#if defined (_ASSERT_H_DECLS) && defined(__GLIBC__)
172 // abort via GLIBC if possible, which allows 'print __abort_msg->msg' from apport/gdb
173 __assert_fail (msg && msg[0] ? msg : "assertion unreachable\n", file, line, func);
174#else
175 for (;;)
176 abort();
177#endif
178}
179} // Ase
abort
access
T back(T... args)
T c_str(T... args)
close
snprintf
T empty(T... args)
errno
fflush
fputs
free
getenv
The Anklang C++ API namespace.
Definition api.hh:9
void assertion_failed(const char *msg, const char *file, int line, const char *func) noexcept
Print instructive message, handle "breakpoint", "backtrace" and "fatal-warnings" in $ASE_DEBUG.
Definition cxxaux.cc:122
void assertion_fatal(const char *msg, const char *file, int line, const char *func) noexcept
Print a debug message via assertion_failed() and abort the program.
Definition cxxaux.cc:110
void perror_die(const std::string &msg) noexcept
Issue a warning about an assertion error.
Definition cxxaux.cc:94
const char * string_demangle_cxx(const char *mangled_identifier) noexcept
Demangle identifier via libcc.
Definition cxxaux.cc:18
std::string backtrace_command()
Find GDB and construct command line.
Definition cxxaux.cc:44
bool assertion_failed_fatal
Global flag to force aborting on assertion warnings.
Definition cxxaux.cc:106
open
read
stdout
strerror
strlen
strstr
system
T to_string(T... args)