Geant4 10.7.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4Backtrace.hh
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26// G4Backtrace
27//
28// Description:
29//
30// Prints backtraces after signals are caught. Available on Unix.
31//
32// Usage:
33// A standard set of signals are enabled by default:
34//
35// SIGQUIT, SIGILL, SIGABRT, SIGKILL, SIGBUS, SIGSEGV
36//
37// These should not interfere with debuggers and/or G4FPEDetection.
38// In order to turn off handling for one or more signals, one can do:
39//
40// G4BackTrace::DefaultSignals() = std::set<int>{};
41// G4BackTrace::DefaultSignals() = std::set<int>{ SIGSEGV };
42//
43// and so on, *before* creating the run-manager. After the run-manager
44// has been created, one should disable the signals:
45//
46// G4BackTrace::Disable(G4BackTrace::DefaultSignals());
47//
48// Additionally, at runtime, the environment variable "G4BACKTRACE" can
49// be set to select a specific set of signals or none, e.g. in bash:
50//
51// export G4BACKTRACE="SIGQUIT,SIGSEGV"
52// export G4BACKTRACE="none"
53//
54// The environment variable is case-insensitive and can use any of the
55// following delimiters: space, comma, semi-colon, colon
56//
57// Author: J.Madsen, 19 October 2020
58// --------------------------------------------------------------------
59
60#ifndef G4Backtrace_hh
61#define G4Backtrace_hh 1
62
63#include "G4Types.hh"
64#include "G4String.hh"
65#include "G4Threading.hh"
66
67#if defined(__APPLE__) || defined(__MACH__)
68# if !defined(G4MACOS)
69# define G4MACOS
70# endif
71# if !defined(G4UNIX)
72# define G4UNIX
73# endif
74#elif defined(__linux__) || defined(__linux) || defined(linux) || \
75 defined(__gnu_linux__)
76# if !defined(G4LINUX)
77# define G4LINUX
78# endif
79# if !defined(G4UNIX)
80# define G4UNIX
81# endif
82#elif defined(__unix__) || defined(__unix) || defined(unix)
83# if !defined(G4UNIX)
84# define G4UNIX
85# endif
86#endif
87
88#if defined(G4UNIX)
89# include <cxxabi.h>
90# include <execinfo.h>
91# include <unistd.h>
92#endif
93
94#if defined(G4LINUX)
95# include <features.h>
96#endif
97
98#include <cfenv>
99#include <csignal>
100#include <type_traits>
101
102template <typename FuncT>
103using G4ResultOf_t = typename std::result_of<FuncT>::type;
104
105// compatible OS and compiler
106#if defined(G4UNIX) && \
107 (defined(__GNUC__) || defined(__clang__) || defined(_INTEL_COMPILER))
108# if !defined(G4SIGNAL_AVAILABLE)
109# define G4SIGNAL_AVAILABLE
110# endif
111# if !defined(G4DEMANGLE_AVAILABLE)
112# define G4DEMANGLE_AVAILABLE
113# endif
114#endif
115
116#if !defined(G4PSIGINFO_AVAILABLE)
117# if _XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L
118# define G4PSIGINFO_AVAILABLE 1
119# else
120# define G4PSIGINFO_AVAILABLE 0
121# endif
122#endif
123
124//----------------------------------------------------------------------------//
125
126inline G4String G4Demangle(const char* _str)
127{
128#if defined(G4DEMANGLE_AVAILABLE)
129 // demangling a string when delimiting
130 int _status = 0;
131 char* _ret = ::abi::__cxa_demangle(_str, nullptr, nullptr, &_status);
132 if(_ret && _status == 0)
133 return G4String(const_cast<const char*>(_ret));
134 return _str;
135#else
136 return _str;
137#endif
138}
139
140//----------------------------------------------------------------------------//
141
142inline G4String G4Demangle(const G4String& _str)
143{
144 return G4Demangle(_str.c_str());
145}
146
147//----------------------------------------------------------------------------//
148
149template <typename Tp>
151{
152 return G4Demangle(typeid(Tp).name());
153}
154
155//----------------------------------------------------------------------------//
156//
157// ONLY IF G4SIGNAL_AVAILABLE
158//
159//----------------------------------------------------------------------------//
160//
161#if defined(G4SIGNAL_AVAILABLE)
162//
163// these are not in the original POSIX.1-1990 standard so we are defining
164// them in case the OS hasn't
165// POSIX-1.2001
166# ifndef SIGTRAP
167# define SIGTRAP 5
168# endif
169// not specified in POSIX.1-2001, but nevertheless appears on most other
170// UNIX systems, where its default action is typically to terminate the
171// process with a core dump.
172# ifndef SIGEMT
173# define SIGEMT 7
174# endif
175// POSIX-1.2001
176# ifndef SIGURG
177# define SIGURG 16
178# endif
179// POSIX-1.2001
180# ifndef SIGXCPU
181# define SIGXCPU 24
182# endif
183// POSIX-1.2001
184# ifndef SIGXFSZ
185# define SIGXFSZ 25
186# endif
187// POSIX-1.2001
188# ifndef SIGVTALRM
189# define SIGVTALRM 26
190# endif
191// POSIX-1.2001
192# ifndef SIGPROF
193# define SIGPROF 27
194# endif
195// POSIX-1.2001
196# ifndef SIGINFO
197# define SIGINFO 29
198# endif
199
200//----------------------------------------------------------------------------//
201
202# include <algorithm>
203# include <array>
204# include <cstdlib>
205# include <functional>
206# include <iomanip>
207# include <iostream>
208# include <map>
209# include <mutex>
210# include <regex>
211# include <set>
212# include <sstream>
213# include <string>
214# include <tuple>
215# include <vector>
216
217//----------------------------------------------------------------------------//
218
219class G4Backtrace
220{
221 public:
222 using sigaction_t = struct sigaction;
223 using exit_action_t = std::function<void(int)>;
224 using frame_func_t = std::function<G4String(const char*)>;
225 using signal_set_t = std::set<int>;
226
227 public:
228 struct actions
229 {
230 using id_entry_t = std::tuple<std::string, int, std::string>;
231 using id_list_t = std::vector<id_entry_t>;
232
233 std::shared_ptr<std::mutex> lock = std::make_shared<std::mutex>();
234 std::map<int, bool> is_active = {};
235 std::map<int, sigaction_t> current = {};
236 std::map<int, sigaction_t> previous = {};
237 std::vector<exit_action_t> exit_actions = {};
238 const id_list_t identifiers = {
239 id_entry_t("SIGHUP", SIGHUP, "terminal line hangup"),
240 id_entry_t("SIGINT", SIGINT, "interrupt program"),
241 id_entry_t("SIGQUIT", SIGQUIT, "quit program"),
242 id_entry_t("SIGILL", SIGILL, "illegal instruction"),
243 id_entry_t("SIGTRAP", SIGTRAP, "trace trap"),
244 id_entry_t("SIGABRT", SIGABRT, "abort program (formerly SIGIOT)"),
245 id_entry_t("SIGEMT", SIGEMT, "emulate instruction executed"),
246 id_entry_t("SIGFPE", SIGFPE, "floating-point exception"),
247 id_entry_t("SIGKILL", SIGKILL, "kill program"),
248 id_entry_t("SIGBUS", SIGBUS, "bus error"),
249 id_entry_t("SIGSEGV", SIGSEGV, "segmentation violation"),
250 id_entry_t("SIGSYS", SIGSYS, "non-existent system call invoked"),
251 id_entry_t("SIGPIPE", SIGPIPE, "write on a pipe with no reader"),
252 id_entry_t("SIGALRM", SIGALRM, "real-time timer expired"),
253 id_entry_t("SIGTERM", SIGTERM, "software termination signal"),
254 id_entry_t("SIGURG", SIGURG, "urgent condition present on socket"),
255 id_entry_t("SIGSTOP", SIGSTOP, "stop (cannot be caught or ignored)"),
256 id_entry_t("SIGTSTP", SIGTSTP, "stop signal generated from keyboard"),
257 id_entry_t("SIGCONT", SIGCONT, "continue after stop"),
258 id_entry_t("SIGCHLD", SIGCHLD, "child status has changed"),
259 id_entry_t("SIGTTIN", SIGTTIN,
260 "background read attempted from control terminal"),
261 id_entry_t("SIGTTOU", SIGTTOU,
262 "background write attempted to control terminal"),
263 id_entry_t("SIGIO ", SIGIO, "I/O is possible on a descriptor"),
264 id_entry_t("SIGXCPU", SIGXCPU, "cpu time limit exceeded"),
265 id_entry_t("SIGXFSZ", SIGXFSZ, "file size limit exceeded"),
266 id_entry_t("SIGVTALRM", SIGVTALRM, "virtual time alarm"),
267 id_entry_t("SIGPROF", SIGPROF, "profiling timer alarm"),
268 id_entry_t("SIGWINCH", SIGWINCH, "Window size change"),
269 id_entry_t("SIGINFO", SIGINFO, "status request from keyboard"),
270 id_entry_t("SIGUSR1", SIGUSR1, "User defined signal 1"),
271 id_entry_t("SIGUSR2", SIGUSR2, "User defined signal 2")
272 };
273 };
274
275 public:
276 // a functor called for each frame in the backtrace
277 static frame_func_t& FrameFunctor();
278 // default set of signals
280 // the signal handler
281 static void Handler(int sig, siginfo_t* sinfo, void* context);
282 // information message about the signal, performs exit-actions
283 // and prints back-trace
284 static void Message(int sig, siginfo_t* sinfo, std::ostream&);
285 // calls user-provided functions after signal is caught but before abort
286 static void ExitAction(int sig);
287 // enable signals via a string (which is tokenized)
288 static int Enable(const std::string&);
289 // enable signals via set of integers, anything less than zero is ignored
290 static int Enable(const signal_set_t& _signals = DefaultSignals());
291 // disable signals
292 static int Disable(signal_set_t _signals = {});
293 // gets the numeric value for a signal name
294 static int GetSignal(const std::string&);
295 // provides a description of the signal
296 static std::string Description(int sig);
297
298 // adds an exit action
299 template <typename FuncT>
300 static void AddExitAction(FuncT&& func);
301
302 // gets a backtrace of "Depth" frames. The offset parameter is used
303 // to ignore initial frames (such as this function). A callback
304 // can be provided to inspect and/or tweak the frame string
305 template <size_t Depth, size_t Offset = 0, typename FuncT = frame_func_t>
306 static std::array<G4ResultOf_t<FuncT(const char*)>, Depth> GetMangled(
307 FuncT&& func = FrameFunctor());
308
309 // gets a demangled backtrace of "Depth" frames. The offset parameter is
310 // used to ignore initial frames (such as this function). A callback
311 // can be provided to inspect and/or tweak the frame string
312 template <size_t Depth, size_t Offset = 0, typename FuncT = frame_func_t>
313 static std::array<G4ResultOf_t<FuncT(const char*)>, Depth> GetDemangled(
314 FuncT&& func = FrameFunctor());
315
316 private:
317 static actions& GetData()
318 {
319 static auto _instance = actions{};
320 return _instance;
321 }
322};
323
324//----------------------------------------------------------------------------//
325
326// a functor called for each frame in the backtrace
328{
329 static frame_func_t _instance = [](const char* inp) { return G4String(inp); };
330 return _instance;
331}
332
333//----------------------------------------------------------------------------//
334
335// default set of signals
337{
338 static signal_set_t _instance = { SIGQUIT, SIGILL, SIGABRT,
339 SIGKILL, SIGBUS, SIGSEGV };
340 return _instance;
341}
342
343//----------------------------------------------------------------------------//
344
345template <typename FuncT>
346inline void G4Backtrace::AddExitAction(FuncT&& func)
347{
348 GetData().exit_actions.emplace_back(std::forward<FuncT>(func));
349}
350
351//----------------------------------------------------------------------------//
352
353inline void G4Backtrace::ExitAction(int sig)
354{
355 for(auto& itr : GetData().exit_actions)
356 itr(sig);
357}
358
359//----------------------------------------------------------------------------//
360
361template <size_t Depth, size_t Offset, typename FuncT>
362inline std::array<G4ResultOf_t<FuncT(const char*)>, Depth>
363G4Backtrace::GetMangled(FuncT&& func)
364{
365 static_assert((Depth - Offset) >= 1, "Error Depth - Offset should be >= 1");
366
367 using type = G4ResultOf_t<FuncT(const char*)>;
368 // destination
369 std::array<type, Depth> btrace;
370 btrace.fill((std::is_pointer<type>::value) ? nullptr : type{});
371
372 // plus one for this stack-frame
373 std::array<void*, Depth + Offset> buffer;
374 // size of returned buffer
375 auto sz = backtrace(buffer.data(), Depth + Offset);
376 // size of relevant data
377 auto n = sz - Offset;
378
379 // skip ahead (Offset + 1) stack frames
380 char** bsym = backtrace_symbols(buffer.data() + Offset, n);
381
382 // report errors
383 if(bsym == nullptr)
384 perror("backtrace_symbols");
385 else
386 {
387 for(decltype(n) i = 0; i < n; ++i)
388 btrace[i] = func(bsym[i]);
389 free(bsym);
390 }
391 return btrace;
392}
393
394//----------------------------------------------------------------------------//
395
396template <size_t Depth, size_t Offset, typename FuncT>
397inline std::array<G4ResultOf_t<FuncT(const char*)>, Depth>
398G4Backtrace::GetDemangled(FuncT&& func)
399{
400 auto demangle_bt = [&](const char* cstr) {
401 auto _trim = [](std::string& _sub, size_t& _len) {
402 size_t _pos = 0;
403 while((_pos = _sub.find_first_of(' ')) == 0)
404 {
405 _sub = _sub.erase(_pos, 1);
406 --_len;
407 }
408 while((_pos = _sub.find_last_of(' ')) == _sub.length() - 1)
409 {
410 _sub = _sub.substr(0, _sub.length() - 1);
411 --_len;
412 }
413 return _sub;
414 };
415
416 auto str = G4Demangle(std::string(cstr));
417 auto beg = str.find("(");
418 if(beg == std::string::npos)
419 {
420 beg = str.find("_Z");
421 if(beg != std::string::npos)
422 beg -= 1;
423 }
424 auto end = str.find("+", beg);
425 if(beg != std::string::npos && end != std::string::npos)
426 {
427 auto len = end - (beg + 1);
428 auto sub = str.substr(beg + 1, len);
429 auto dem = G4Demangle(_trim(sub, len));
430 str = str.replace(beg + 1, len, dem);
431 }
432 else if(beg != std::string::npos)
433 {
434 auto len = str.length() - (beg + 1);
435 auto sub = str.substr(beg + 1, len);
436 auto dem = G4Demangle(_trim(sub, len));
437 str = str.replace(beg + 1, len, dem);
438 }
439 else if(end != std::string::npos)
440 {
441 auto len = end;
442 auto sub = str.substr(beg, len);
443 auto dem = G4Demangle(_trim(sub, len));
444 str = str.replace(beg, len, dem);
445 }
446 return func(str.c_str());
447 };
448 return GetMangled<Depth, Offset>(demangle_bt);
449}
450
451//----------------------------------------------------------------------------//
452
453inline void G4Backtrace::Message(int sig, siginfo_t* sinfo, std::ostream& os)
454{
455 std::stringstream message;
456 message << "\n### CAUGHT SIGNAL: " << sig << " ### ";
457 if(sinfo)
458 message << "address: " << sinfo->si_addr << ", ";
459 message << Description(sig) << ". ";
460
461 if(sig == SIGSEGV)
462 {
463 if(sinfo)
464 {
465 switch(sinfo->si_code)
466 {
467 case SEGV_MAPERR:
468 message << "Address not mapped to object.";
469 break;
470 case SEGV_ACCERR:
471 message << "Invalid permissions for mapped object.";
472 break;
473 default:
474 message << "Unknown segmentation fault error: " << sinfo->si_code
475 << ".";
476 break;
477 }
478 }
479 else
480 {
481 message << "Segmentation fault (unknown).";
482 }
483 }
484 else if(sig == SIGFPE)
485 {
486 if(sinfo)
487 {
488 switch(sinfo->si_code)
489 {
490 case FE_DIVBYZERO:
491 message << "Floating point divide by zero.";
492 break;
493 case FE_OVERFLOW:
494 message << "Floating point overflow.";
495 break;
496 case FE_UNDERFLOW:
497 message << "Floating point underflow.";
498 break;
499 case FE_INEXACT:
500 message << "Floating point inexact result.";
501 break;
502 case FE_INVALID:
503 message << "Floating point invalid operation.";
504 break;
505 default:
506 message << "Unknown floating point exception error: "
507 << sinfo->si_code << ".";
508 break;
509 }
510 }
511 else
512 {
513 message << "Unknown floating point exception";
514 if(sinfo)
515 message << ": " << sinfo->si_code;
516 message << ". ";
517 }
518 }
519
520 message << std::endl;
521 try
522 {
523 sigignore(sig);
524 ExitAction(sig);
525 } catch(std::exception& e)
526 {
527 std::cerr << "ExitAction(" << sig << ") threw an exception" << std::endl;
528 std::cerr << e.what() << std::endl;
529 }
530
531 auto bt = GetDemangled<256, 3>(FrameFunctor());
532 std::stringstream prefix;
533 prefix << "[PID=" << getpid() << ", TID=" << G4Threading::G4GetThreadId()
534 << "]";
535 std::vector<G4String> btvec;
536 for(auto& itr : bt)
537 {
538 if(itr.length() > 0)
539 btvec.emplace_back(std::move(itr));
540 }
541 std::stringstream serr;
542 serr << "\nBacktrace:\n";
543 auto _w = std::log10(btvec.size()) + 1;
544 for(size_t i = 0; i < btvec.size(); ++i)
545 {
546 serr << prefix.str() << "[" << std::setw(_w) << std::right << i << '/'
547 << std::setw(_w) << std::right << btvec.size() << "]> " << std::left
548 << btvec.at(i) << '\n';
549 }
550 os << serr.str().c_str() << '\n';
551 os << message.str() << std::flush;
552}
553
554//----------------------------------------------------------------------------//
555
556inline void G4Backtrace::Handler(int sig, siginfo_t* sinfo, void*)
557{
558 std::unique_lock<std::mutex> lk{ *(GetData().lock) };
559
560 {
561 std::stringstream msg;
562 Message(sig, sinfo, msg);
563 std::cerr << msg.str() << std::flush;
564 }
565
566 std::stringstream msg;
567 msg << "\n\n";
568
569 if(sinfo && G4PSIGINFO_AVAILABLE > 0)
570 {
571# if G4PSIGINFO_AVAILABLE > 0
572 psiginfo(sinfo, msg.str().c_str());
573# endif
574 }
575 else
576 {
577 std::cerr << msg.str() << std::endl;
578 }
579
580 // ignore any termination signals
581 sigignore(SIGKILL);
582 sigignore(SIGTERM);
583 sigignore(SIGABRT);
584 abort();
585}
586
587//----------------------------------------------------------------------------//
588
589inline int G4Backtrace::Enable(const signal_set_t& _signals)
590{
591 static bool _first = true;
592 std::unique_lock<std::mutex> lk{ *(GetData().lock) };
593 if(_first)
594 {
595 std::string _msg = "!!! G4Backtrace is activated !!!";
596 std::stringstream _filler;
597 std::stringstream _spacer;
598 _filler.fill('#');
599 _filler << std::setw(_msg.length()) << "";
600 _spacer << std::setw(10) << "";
601 std::cout << "\n\n"
602 << _spacer.str() << _filler.str() << "\n"
603 << _spacer.str() << _msg << "\n"
604 << _spacer.str() << _filler.str() << "\n\n"
605 << std::flush;
606 }
607 _first = false;
608 int cnt = 0;
609 for(auto& itr : _signals)
610 {
611 if(itr < 0)
612 continue;
613 if(GetData().is_active[itr])
614 continue;
615 ++cnt;
616 sigfillset(&(GetData().current[itr].sa_mask));
617 sigdelset(&(GetData().current[itr].sa_mask), itr);
618 GetData().current[itr].sa_sigaction = &Handler;
619 GetData().current[itr].sa_flags = SA_SIGINFO;
620 sigaction(itr, &(GetData().current[itr]), &(GetData().previous[itr]));
621 }
622 return cnt;
623}
624
625//----------------------------------------------------------------------------//
626
627inline int G4Backtrace::Enable(const std::string& _signals)
628{
629 if(_signals.empty())
630 return 0;
631
632 auto _add_signal = [](std::string sig, signal_set_t& _targ) {
633 if(!sig.empty())
634 {
635 for(auto& itr : sig)
636 itr = toupper(itr);
637 _targ.insert(G4Backtrace::GetSignal(sig));
638 }
639 };
640
641 const std::regex wsp_re("[ ,;:\t\n]+");
642 auto _maxid = GetData().identifiers.size();
643 auto _result = std::vector<std::string>(_maxid, "");
644 std::copy(
645 std::sregex_token_iterator(_signals.begin(), _signals.end(), wsp_re, -1),
646 std::sregex_token_iterator(), _result.begin());
647 signal_set_t _sigset{};
648 for(auto& itr : _result)
649 _add_signal(itr, _sigset);
650 return Enable(_sigset);
651}
652
653//----------------------------------------------------------------------------//
654
655inline int G4Backtrace::Disable(signal_set_t _signals)
656{
657 std::unique_lock<std::mutex> lk{ *(GetData().lock) };
658
659 if(_signals.empty())
660 {
661 for(auto& itr : GetData().is_active)
662 _signals.insert(itr.first);
663 }
664
665 int cnt = 0;
666 for(auto& itr : _signals)
667 {
668 if(itr < 0)
669 continue;
670 if(!GetData().is_active[itr])
671 continue;
672 ++cnt;
673 sigaction(itr, &(GetData().previous[itr]), nullptr);
674 GetData().current.erase(itr);
675 GetData().is_active[itr] = false;
676 }
677 return cnt;
678}
679
680//----------------------------------------------------------------------------//
681
682inline int G4Backtrace::GetSignal(const std::string& sid)
683{
684 for(auto&& itr : GetData().identifiers)
685 {
686 if(std::get<0>(itr) == sid)
687 return std::get<1>(itr);
688 }
689 return -1;
690}
691
692//----------------------------------------------------------------------------//
693
694inline std::string G4Backtrace::Description(int sig)
695{
696 for(auto&& itr : GetData().identifiers)
697 {
698 if(std::get<1>(itr) == sig)
699 {
700 std::stringstream ss;
701 ss << " signal = " << std::setw(8) << std::get<0>(itr)
702 << ", value = " << std::setw(4) << std::get<1>(itr)
703 << ", description = " << std::get<2>(itr);
704 return ss.str();
705 }
706 }
707 std::stringstream ss;
708 ss << " signal = " << std::setw(8) << "unknown"
709 << ", value = " << std::setw(4) << sig;
710 return ss.str();
711}
712
713//----------------------------------------------------------------------------//
714
715#else
716
717# include <array>
718# include <functional>
719# include <map>
720# include <set>
721# include <string>
722# include <tuple>
723# include <vector>
724
725// dummy implementation
727{
728 public:
730 {};
732 {};
733
736 using exit_action_t = std::function<void(int)>;
737 using frame_func_t = std::function<G4String(const char*)>;
738 using signal_set_t = std::set<int>;
739
740 public:
741 struct actions
742 {
743 using id_entry_t = std::tuple<std::string, int, std::string>;
744 using id_list_t = std::vector<id_entry_t>;
745
746 std::map<int, bool> is_active = {};
747 std::map<int, sigaction_t> current = {};
748 std::map<int, sigaction_t> previous = {};
749 std::vector<exit_action_t> exit_actions = {};
751 };
752
753 public:
754 static void Handler(int, siginfo_t*, void*) {}
755 static void Message(int, siginfo_t*, std::ostream&) {}
756 static void ExitAction(int) {}
757 static int Enable(const std::string&) { return 0; }
758 static int Enable(const signal_set_t& = DefaultSignals()) { return 0; }
759 static int Disable(signal_set_t = {}) { return 0; }
760 static int GetSignal(const std::string&) { return -1; }
761 static std::string Description(int) { return std::string{}; }
762
763 template <typename FuncT>
764 static void AddExitAction(FuncT&&)
765 {}
766
767 template <size_t Depth, size_t Offset = 0, typename FuncT = frame_func_t>
768 static std::array<G4ResultOf_t<FuncT(const char*)>, Depth> GetMangled(
769 FuncT&& func = FrameFunctor())
770 {
771 using type = G4ResultOf_t<FuncT(const char*)>;
772 auto ret = std::array<type, Depth>{};
773 ret.fill(func(""));
774 return ret;
775 }
776
777 template <size_t Depth, size_t Offset = 0, typename FuncT = frame_func_t>
778 static std::array<G4ResultOf_t<FuncT(const char*)>, Depth> GetDemangled(
779 FuncT&& func = FrameFunctor())
780 {
781 using type = G4ResultOf_t<FuncT(const char*)>;
782 auto ret = std::array<type, Depth>{};
783 ret.fill(func(""));
784 return ret;
785 }
786
787 // a functor called for each frame in the backtrace
789 {
790 static frame_func_t _instance = [](const char* _s) { return G4String(_s); };
791 return _instance;
792 }
793
794 // default set of signals
796 {
797 static signal_set_t _instance = {};
798 return _instance;
799 }
800
801 static actions& GetData()
802 {
803 static auto _instance = actions{};
804 return _instance;
805 }
806};
807
808//----------------------------------------------------------------------------//
809
810#endif // G4SIGNAL_AVAILABLE
811#endif // G4Backtrace_hh
typename std::result_of< FuncT >::type G4ResultOf_t
Definition: G4Backtrace.hh:103
#define G4PSIGINFO_AVAILABLE
Definition: G4Backtrace.hh:120
G4String G4Demangle()
Definition: G4Backtrace.hh:150
static void Handler(int, siginfo_t *, void *)
Definition: G4Backtrace.hh:754
fake_sigaction sigaction_t
Definition: G4Backtrace.hh:735
static std::string Description(int)
Definition: G4Backtrace.hh:761
static signal_set_t & DefaultSignals()
Definition: G4Backtrace.hh:795
static int Enable(const std::string &)
Definition: G4Backtrace.hh:757
static void ExitAction(int)
Definition: G4Backtrace.hh:756
static void AddExitAction(FuncT &&)
Definition: G4Backtrace.hh:764
static frame_func_t & FrameFunctor()
Definition: G4Backtrace.hh:788
static actions & GetData()
Definition: G4Backtrace.hh:801
std::set< int > signal_set_t
Definition: G4Backtrace.hh:738
static int GetSignal(const std::string &)
Definition: G4Backtrace.hh:760
static std::array< G4ResultOf_t< FuncT(const char *)>, Depth > GetMangled(FuncT &&func=FrameFunctor())
Definition: G4Backtrace.hh:768
std::function< void(int)> exit_action_t
Definition: G4Backtrace.hh:736
fake_siginfo siginfo_t
Definition: G4Backtrace.hh:734
std::function< G4String(const char *)> frame_func_t
Definition: G4Backtrace.hh:737
static void Message(int, siginfo_t *, std::ostream &)
Definition: G4Backtrace.hh:755
static std::array< G4ResultOf_t< FuncT(const char *)>, Depth > GetDemangled(FuncT &&func=FrameFunctor())
Definition: G4Backtrace.hh:778
static int Enable(const signal_set_t &=DefaultSignals())
Definition: G4Backtrace.hh:758
static int Disable(signal_set_t={})
Definition: G4Backtrace.hh:759
G4int G4GetThreadId()
Definition: G4Threading.cc:122
std::map< int, sigaction_t > previous
Definition: G4Backtrace.hh:748
std::vector< exit_action_t > exit_actions
Definition: G4Backtrace.hh:749
const id_list_t identifiers
Definition: G4Backtrace.hh:750
std::map< int, bool > is_active
Definition: G4Backtrace.hh:746
std::vector< id_entry_t > id_list_t
Definition: G4Backtrace.hh:744
std::map< int, sigaction_t > current
Definition: G4Backtrace.hh:747
std::tuple< std::string, int, std::string > id_entry_t
Definition: G4Backtrace.hh:743
#define buffer
Definition: xmlparse.cc:628