34#include "timemory/backends/dmp.hpp"
35#include "timemory/backends/process.hpp"
36#include "timemory/backends/signals.hpp"
37#include "timemory/backends/threading.hpp"
44#include <initializer_list>
48#if defined(SIGNAL_AVAILABLE)
63 enable_if_t<!std::is_enum<Tp>::value && std::is_integral<Tp>::value> = 0>
86#if defined(SIGNAL_AVAILABLE)
88termination_signal_message(
int sig, siginfo_t* sinfo, std::ostream& message);
95#if defined(SIGNAL_AVAILABLE)
103timemory_termination_signal_handler(
int sig, siginfo_t* sinfo,
void* )
110 std::stringstream ss;
111 ss <<
"signal " << sig <<
" not caught";
115 tim::termination_signal_message(sig, sinfo, std::cerr);
119 std::stringstream message;
122# if defined(PSIGINFO_AVAILABLE)
125 psiginfo(sinfo, message.str().c_str());
129 std::cerr << message.str() << std::endl;
132 std::cerr << message.str() << std::endl;
143static struct sigaction&
144tim_signal_termaction()
146 static struct sigaction _instance;
152static struct sigaction&
153tim_signal_oldaction()
155 static struct sigaction _instance;
162termination_signal_message(
int sig, siginfo_t* sinfo, std::ostream&
os)
168 message <<
"\n### ERROR ### ";
169 if(dmp::is_initialized())
170 message <<
" [ rank : " << dmp::rank() <<
" ] ";
171 message <<
"Error code : " << sig;
173 message <<
" @ " << sinfo->si_addr;
180 switch(sinfo->si_code)
182 case SEGV_MAPERR: message <<
"Address not mapped to object.";
break;
184 message <<
"Invalid permissions for mapped object.";
187 message <<
"Unknown segmentation fault error: " << sinfo->si_code
194 message <<
"Segmentation fault (unknown).";
197 else if(sig == SIGFPE)
201 switch(sinfo->si_code)
203 case FE_DIVBYZERO: message <<
"Floating point divide by zero.";
break;
204 case FE_OVERFLOW: message <<
"Floating point overflow.";
break;
205 case FE_UNDERFLOW: message <<
"Floating point underflow.";
break;
206 case FE_INEXACT: message <<
"Floating point inexact result.";
break;
207 case FE_INVALID: message <<
"Floating point invalid operation.";
break;
209 message <<
"Unknown floating point exception error: "
210 << sinfo->si_code <<
".";
216 message <<
"Unknown error.";
220 message << std::endl;
225 memset(prefix,
'\0', 512 *
sizeof(
char));
226 sprintf(prefix,
"[PID=%i][TID=%i]", (
int) process::get_id(),
227 (
int) threading::get_id());
230 auto bt = tim::get_backtrace<32>();
231 for(
const auto& itr : bt)
238 std::stringstream serr;
239 serr <<
"\nBacktrace:\n";
240 for(
size_t i = 0; i < bt.size(); ++i)
244 if(strlen(bt.at(i)) == 0)
246 message << prefix <<
"[" << i <<
'/' << ntot <<
"]> " << bt.at(i) <<
"\n";
255 }
catch(std::exception& e)
257 std::cerr <<
"signal_settings::exit_action(" << sig <<
") threw an exception"
259 std::cerr << e.what() << std::endl;
279 if(operations.empty())
286 if(!_enabled.empty())
288 for(
const auto& itr : _enabled)
292 for(
const auto& itr : operations)
296 std::set<int> _signals;
297 for(
auto operation : operations)
298 _signals.insert(
static_cast<int>(operation));
300 sigfillset(&tim_signal_termaction().sa_mask);
301 for(
const auto& itr : _signals)
302 sigdelset(&tim_signal_termaction().sa_mask, itr);
303 tim_signal_termaction().sa_sigaction = timemory_termination_signal_handler;
304 tim_signal_termaction().sa_flags = SA_SIGINFO;
305 for(
const auto& itr : _signals)
307 sigaction(itr, &tim_signal_termaction(), &tim_signal_oldaction());
319template <
typename Tp,
320 enable_if_t<!std::is_enum<Tp>::value && std::is_integral<Tp>::value>>
325 for(
const auto& itr : _signals)
326 operations.insert(
static_cast<sys_signal>(itr));
339 sigemptyset(&tim_signal_termaction().sa_mask);
340 tim_signal_termaction().sa_handler = SIG_DFL;
345 int _itr =
static_cast<int>(itr);
346 sigaction(_itr, &tim_signal_termaction(),
nullptr);
370template <
typename Tp,
371 enable_if_t<!std::is_enum<Tp>::value && std::is_integral<Tp>::value>>
static std::string str(const sys_signal &)
static void enable(const sys_signal &)
static void check_environment()
static void exit_action(int errcode)
static void disable(const sys_signal &)
static signal_set_t get_enabled()
std::set< sys_signal > signal_set_t
static void set_active(bool val)
static signal_set_t get_disabled()
static signal_set_t get_default()
bool enable_signal_detection(signal_settings::signal_set_t=signal_settings::get_default())
void disable_signal_detection()
const std::string std::ostream * os
void update_signal_detection(const signal_settings::signal_set_t &_signals)
The declaration for the types for utility without definitions.
#define TIMEMORY_EXCEPTION(...)