Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/global/management/include/G4Backtrace.hh

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

Diff markup

Differences between /global/management/include/G4Backtrace.hh (Version 11.3.0) and /global/management/include/G4Backtrace.hh (Version 11.1.2)


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