File indexing completed on 2025-01-18 09:57:57
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060 #ifndef G4Backtrace_hh
0061 #define G4Backtrace_hh 1
0062
0063 #include "G4Types.hh"
0064 #include "G4String.hh"
0065 #include "G4Threading.hh"
0066
0067 #if defined(__APPLE__) || defined(__MACH__)
0068 # if !defined(G4MACOS)
0069 # define G4MACOS
0070 # endif
0071 # if !defined(G4UNIX)
0072 # define G4UNIX
0073 # endif
0074 #elif defined(__linux__) || defined(__linux) || defined(linux) || \
0075 defined(__gnu_linux__)
0076 # if !defined(G4LINUX)
0077 # define G4LINUX
0078 # endif
0079 # if !defined(G4UNIX)
0080 # define G4UNIX
0081 # endif
0082 #elif defined(__unix__) || defined(__unix) || defined(unix)
0083 # if !defined(G4UNIX)
0084 # define G4UNIX
0085 # endif
0086 #endif
0087
0088 #if defined(G4UNIX) && !defined(WIN32)
0089 # include <cxxabi.h>
0090 # include <execinfo.h>
0091 # include <unistd.h>
0092 #endif
0093
0094 #if defined(G4LINUX)
0095 # include <features.h>
0096 #endif
0097
0098 #include <cfenv>
0099 #include <csignal>
0100 #include <type_traits>
0101
0102 template <typename FuncT, typename... ArgTypes>
0103 using G4ResultOf_t = std::invoke_result_t<FuncT, ArgTypes...>;
0104
0105
0106 #if defined(G4UNIX) && \
0107 (defined(__GNUC__) || defined(__clang__) || defined(_INTEL_COMPILER))
0108 # if !defined(G4SIGNAL_AVAILABLE)
0109 # define G4SIGNAL_AVAILABLE
0110 # endif
0111 # if !defined(G4DEMANGLE_AVAILABLE)
0112 # define G4DEMANGLE_AVAILABLE
0113 # endif
0114 #endif
0115
0116 #if !defined(G4PSIGINFO_AVAILABLE)
0117 # if _XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L
0118 # define G4PSIGINFO_AVAILABLE 1
0119 # else
0120 # define G4PSIGINFO_AVAILABLE 0
0121 # endif
0122 #endif
0123
0124
0125
0126 inline G4String G4Demangle(const char* _str)
0127 {
0128 #if defined(G4DEMANGLE_AVAILABLE)
0129
0130 G4int _status = 0;
0131 char* _ret = ::abi::__cxa_demangle(_str, nullptr, nullptr, &_status);
0132 if((_ret != nullptr) && _status == 0)
0133 return G4String(const_cast<const char*>(_ret));
0134 return _str;
0135 #else
0136 return _str;
0137 #endif
0138 }
0139
0140
0141
0142 inline G4String G4Demangle(const G4String& _str)
0143 {
0144 return G4Demangle(_str.c_str());
0145 }
0146
0147
0148
0149 template <typename Tp>
0150 inline G4String G4Demangle()
0151 {
0152 return G4Demangle(typeid(Tp).name());
0153 }
0154
0155
0156
0157
0158
0159
0160
0161 #if defined(G4SIGNAL_AVAILABLE)
0162
0163
0164
0165
0166 # ifndef SIGTRAP
0167 # define SIGTRAP 5
0168 # endif
0169
0170
0171
0172 # ifndef SIGEMT
0173 # define SIGEMT 7
0174 # endif
0175
0176 # ifndef SIGURG
0177 # define SIGURG 16
0178 # endif
0179
0180 # ifndef SIGXCPU
0181 # define SIGXCPU 24
0182 # endif
0183
0184 # ifndef SIGXFSZ
0185 # define SIGXFSZ 25
0186 # endif
0187
0188 # ifndef SIGVTALRM
0189 # define SIGVTALRM 26
0190 # endif
0191
0192 # ifndef SIGPROF
0193 # define SIGPROF 27
0194 # endif
0195
0196 # ifndef SIGINFO
0197 # define SIGINFO 29
0198 # endif
0199
0200
0201
0202 # include <algorithm>
0203 # include <array>
0204 # include <cstdlib>
0205 # include <cstdio>
0206 # include <functional>
0207 # include <iomanip>
0208 # include <iostream>
0209 # include <map>
0210 # include <regex>
0211 # include <set>
0212 # include <sstream>
0213 # include <string>
0214 # include <tuple>
0215 # include <vector>
0216
0217
0218
0219 class G4Backtrace
0220 {
0221 public:
0222 using sigaction_t = struct sigaction;
0223 using exit_action_t = std::function<void(G4int)>;
0224 using frame_func_t = std::function<G4String(const char*)>;
0225 using signal_set_t = std::set<G4int>;
0226
0227 public:
0228 struct actions
0229 {
0230 using id_entry_t = std::tuple<std::string, G4int, std::string>;
0231 using id_list_t = std::vector<id_entry_t>;
0232
0233 std::map<G4int, G4bool> is_active = {};
0234 std::map<G4int, sigaction_t> current = {};
0235 std::map<G4int, sigaction_t> previous = {};
0236 std::vector<exit_action_t> exit_actions = {};
0237 const id_list_t identifiers = {
0238 id_entry_t("SIGHUP", SIGHUP, "terminal line hangup"),
0239 id_entry_t("SIGINT", SIGINT, "interrupt program"),
0240 id_entry_t("SIGQUIT", SIGQUIT, "quit program"),
0241 id_entry_t("SIGILL", SIGILL, "illegal instruction"),
0242 id_entry_t("SIGTRAP", SIGTRAP, "trace trap"),
0243 id_entry_t("SIGABRT", SIGABRT, "abort program (formerly SIGIOT)"),
0244 id_entry_t("SIGEMT", SIGEMT, "emulate instruction executed"),
0245 id_entry_t("SIGFPE", SIGFPE, "floating-point exception"),
0246 id_entry_t("SIGKILL", SIGKILL, "kill program"),
0247 id_entry_t("SIGBUS", SIGBUS, "bus error"),
0248 id_entry_t("SIGSEGV", SIGSEGV, "segmentation violation"),
0249 id_entry_t("SIGSYS", SIGSYS, "non-existent system call invoked"),
0250 id_entry_t("SIGPIPE", SIGPIPE, "write on a pipe with no reader"),
0251 id_entry_t("SIGALRM", SIGALRM, "real-time timer expired"),
0252 id_entry_t("SIGTERM", SIGTERM, "software termination signal"),
0253 id_entry_t("SIGURG", SIGURG, "urgent condition present on socket"),
0254 id_entry_t("SIGSTOP", SIGSTOP, "stop (cannot be caught or ignored)"),
0255 id_entry_t("SIGTSTP", SIGTSTP, "stop signal generated from keyboard"),
0256 id_entry_t("SIGCONT", SIGCONT, "continue after stop"),
0257 id_entry_t("SIGCHLD", SIGCHLD, "child status has changed"),
0258 id_entry_t("SIGTTIN", SIGTTIN,
0259 "background read attempted from control terminal"),
0260 id_entry_t("SIGTTOU", SIGTTOU,
0261 "background write attempted to control terminal"),
0262 id_entry_t("SIGIO ", SIGIO, "I/O is possible on a descriptor"),
0263 id_entry_t("SIGXCPU", SIGXCPU, "cpu time limit exceeded"),
0264 id_entry_t("SIGXFSZ", SIGXFSZ, "file size limit exceeded"),
0265 id_entry_t("SIGVTALRM", SIGVTALRM, "virtual time alarm"),
0266 id_entry_t("SIGPROF", SIGPROF, "profiling timer alarm"),
0267 id_entry_t("SIGWINCH", SIGWINCH, "Window size change"),
0268 id_entry_t("SIGINFO", SIGINFO, "status request from keyboard"),
0269 id_entry_t("SIGUSR1", SIGUSR1, "User defined signal 1"),
0270 id_entry_t("SIGUSR2", SIGUSR2, "User defined signal 2")
0271 };
0272 };
0273
0274 public:
0275
0276 static frame_func_t& FrameFunctor();
0277
0278 static signal_set_t& DefaultSignals();
0279
0280 static void Handler(G4int sig, siginfo_t* sinfo, void* context);
0281
0282
0283 static void Message(G4int sig, siginfo_t* sinfo, std::ostream&);
0284
0285 static void ExitAction(G4int sig);
0286
0287 static G4int Enable(const std::string&);
0288
0289 static G4int Enable(const signal_set_t& _signals = DefaultSignals());
0290
0291 static G4int Disable(signal_set_t _signals = {});
0292
0293 static G4int GetSignal(const std::string&);
0294
0295 static std::string Description(G4int sig);
0296
0297
0298 template <typename FuncT>
0299 static void AddExitAction(FuncT&& func);
0300
0301
0302
0303
0304 template <std::size_t Depth, std::size_t Offset = 0, typename FuncT = frame_func_t>
0305 static std::array<G4ResultOf_t<FuncT, const char*>, Depth> GetMangled(
0306 FuncT&& func = FrameFunctor());
0307
0308
0309
0310
0311 template <std::size_t Depth, std::size_t Offset = 0, typename FuncT = frame_func_t>
0312 static std::array<G4ResultOf_t<FuncT, const char*>, Depth> GetDemangled(
0313 FuncT&& func = FrameFunctor());
0314
0315 private:
0316 static actions& GetData()
0317 {
0318 static auto _instance = actions{};
0319 return _instance;
0320 }
0321 };
0322
0323
0324
0325
0326 inline G4Backtrace::frame_func_t& G4Backtrace::FrameFunctor()
0327 {
0328 static frame_func_t _instance = [](const char* inp) { return G4String(inp); };
0329 return _instance;
0330 }
0331
0332
0333
0334
0335 inline G4Backtrace::signal_set_t& G4Backtrace::DefaultSignals()
0336 {
0337 static signal_set_t _instance = { SIGQUIT, SIGILL, SIGABRT,
0338 SIGKILL, SIGBUS, SIGSEGV };
0339 return _instance;
0340 }
0341
0342
0343
0344 template <typename FuncT>
0345 inline void G4Backtrace::AddExitAction(FuncT&& func)
0346 {
0347 GetData().exit_actions.emplace_back(std::forward<FuncT>(func));
0348 }
0349
0350
0351
0352 inline void G4Backtrace::ExitAction(G4int sig)
0353 {
0354 for(auto& itr : GetData().exit_actions)
0355 itr(sig);
0356 }
0357
0358
0359
0360 template <std::size_t Depth, std::size_t Offset, typename FuncT>
0361 inline std::array<G4ResultOf_t<FuncT, const char*>, Depth>
0362 G4Backtrace::GetMangled(FuncT&& func)
0363 {
0364 static_assert((Depth - Offset) >= 1, "Error Depth - Offset should be >= 1");
0365
0366 using type = G4ResultOf_t<FuncT, const char*>;
0367
0368 std::array<type, Depth> btrace;
0369 btrace.fill((std::is_pointer<type>::value) ? nullptr : type{});
0370
0371
0372 std::array<void*, Depth + Offset> buffer;
0373
0374 auto sz = backtrace(buffer.data(), Depth + Offset);
0375
0376 auto n = sz - Offset;
0377
0378
0379 char** bsym = backtrace_symbols(buffer.data() + Offset, (G4int)n);
0380
0381
0382 if(bsym == nullptr)
0383 perror("backtrace_symbols");
0384 else
0385 {
0386 for(decltype(n) i = 0; i < n; ++i)
0387 btrace[i] = func(bsym[i]);
0388 free(bsym);
0389 }
0390 return btrace;
0391 }
0392
0393
0394
0395 template <std::size_t Depth, std::size_t Offset, typename FuncT>
0396 inline std::array<G4ResultOf_t<FuncT, const char*>, Depth>
0397 G4Backtrace::GetDemangled(FuncT&& func)
0398 {
0399 auto demangle_bt = [&](const char* cstr) {
0400 auto _trim = [](std::string& _sub, std::size_t& _len) {
0401 std::size_t _pos = 0;
0402 while((_pos = _sub.find_first_of(' ')) == 0)
0403 {
0404 _sub = _sub.erase(_pos, 1);
0405 --_len;
0406 }
0407 while((_pos = _sub.find_last_of(' ')) == _sub.length() - 1)
0408 {
0409 _sub = _sub.substr(0, _sub.length() - 1);
0410 --_len;
0411 }
0412 return _sub;
0413 };
0414
0415 auto str = G4Demangle(std::string(cstr));
0416 auto beg = str.find('(');
0417 if(beg == std::string::npos)
0418 {
0419 beg = str.find("_Z");
0420 if(beg != std::string::npos)
0421 beg -= 1;
0422 }
0423 auto end = str.find('+', beg);
0424 if(beg != std::string::npos && end != std::string::npos)
0425 {
0426 auto len = end - (beg + 1);
0427 auto sub = str.substr(beg + 1, len);
0428 auto dem = G4Demangle(_trim(sub, len));
0429 str = str.replace(beg + 1, len, dem);
0430 }
0431 else if(beg != std::string::npos)
0432 {
0433 auto len = str.length() - (beg + 1);
0434 auto sub = str.substr(beg + 1, len);
0435 auto dem = G4Demangle(_trim(sub, len));
0436 str = str.replace(beg + 1, len, dem);
0437 }
0438 else if(end != std::string::npos)
0439 {
0440 auto len = end;
0441 auto sub = str.substr(beg, len);
0442 auto dem = G4Demangle(_trim(sub, len));
0443 str = str.replace(beg, len, dem);
0444 }
0445 return func(str.c_str());
0446 };
0447 return GetMangled<Depth, Offset>(demangle_bt);
0448 }
0449
0450
0451
0452 inline void G4Backtrace::Message(G4int sig, siginfo_t* sinfo, std::ostream& os)
0453 {
0454
0455
0456
0457
0458 signal(sig, SIG_IGN);
0459
0460 os << "\n### CAUGHT SIGNAL: " << sig << " ### ";
0461 if(sinfo != nullptr)
0462 os << "address: " << sinfo->si_addr << ", ";
0463 os << Description(sig) << ". ";
0464
0465 if(sig == SIGSEGV)
0466 {
0467 if(sinfo != nullptr)
0468 {
0469 switch(sinfo->si_code)
0470 {
0471 case SEGV_MAPERR:
0472 os << "Address not mapped to object.";
0473 break;
0474 case SEGV_ACCERR:
0475 os << "Invalid permissions for mapped object.";
0476 break;
0477 default:
0478 os << "Unknown segmentation fault error: " << sinfo->si_code << ".";
0479 break;
0480 }
0481 }
0482 else
0483 {
0484 os << "Segmentation fault (unknown).";
0485 }
0486 }
0487 else if(sig == SIGFPE)
0488 {
0489 if(sinfo != nullptr)
0490 {
0491 switch(sinfo->si_code)
0492 {
0493 case FE_DIVBYZERO:
0494 os << "Floating point divide by zero.";
0495 break;
0496 case FE_OVERFLOW:
0497 os << "Floating point overflow.";
0498 break;
0499 case FE_UNDERFLOW:
0500 os << "Floating point underflow.";
0501 break;
0502 case FE_INEXACT:
0503 os << "Floating point inexact result.";
0504 break;
0505 case FE_INVALID:
0506 os << "Floating point invalid operation.";
0507 break;
0508 default:
0509 os << "Unknown floating point exception error: " << sinfo->si_code
0510 << ".";
0511 break;
0512 }
0513 }
0514 else
0515 {
0516 os << "Unknown floating point exception";
0517 if(sinfo != nullptr)
0518 os << ": " << sinfo->si_code;
0519 os << ". ";
0520 }
0521 }
0522
0523 os << '\n';
0524
0525 auto bt = GetMangled<256, 3>([](const char* _s) { return _s; });
0526 char prefix[64];
0527 snprintf(prefix, 64, "[PID=%i, TID=%i]", (G4int) getpid(),
0528 (G4int) G4Threading::G4GetThreadId());
0529 std::size_t sz = 0;
0530 for(auto& itr : bt)
0531 {
0532 if(itr == nullptr)
0533 break;
0534 if(strlen(itr) == 0)
0535 break;
0536 ++sz;
0537 }
0538 os << "\nBacktrace:\n";
0539 auto _w = std::log10(sz) + 1;
0540 for(std::size_t i = 0; i < sz; ++i)
0541 {
0542 os << prefix << "[" << std::setw(_w) << std::right << i << '/'
0543 << std::setw(_w) << std::right << sz << "]> " << std::left << bt.at(i)
0544 << '\n';
0545 }
0546 os << std::flush;
0547
0548
0549
0550 try
0551 {
0552 ExitAction(sig);
0553 } catch(std::exception& e)
0554 {
0555 std::cerr << "ExitAction(" << sig << ") threw an exception" << std::endl;
0556 std::cerr << e.what() << std::endl;
0557 }
0558 }
0559
0560
0561
0562 inline void G4Backtrace::Handler(G4int sig, siginfo_t* sinfo, void*)
0563 {
0564 Message(sig, sinfo, std::cerr);
0565
0566 char msg[1024];
0567 snprintf(msg, 1024, "%s", "\n");
0568
0569 if((sinfo != nullptr) && G4PSIGINFO_AVAILABLE > 0)
0570 {
0571 # if G4PSIGINFO_AVAILABLE > 0
0572 psiginfo(sinfo, msg);
0573 fflush(stdout);
0574 fflush(stderr);
0575 # endif
0576 }
0577 else
0578 {
0579 std::cerr << msg << std::flush;
0580 }
0581
0582
0583 signal(SIGKILL, SIG_IGN);
0584 signal(SIGTERM, SIG_IGN);
0585 signal(SIGABRT, SIG_IGN);
0586 abort();
0587 }
0588
0589
0590
0591 inline G4int G4Backtrace::Enable(const signal_set_t& _signals)
0592 {
0593 static G4bool _first = true;
0594 if(_first)
0595 {
0596 std::string _msg = "!!! G4Backtrace is activated !!!";
0597 std::stringstream _filler;
0598 std::stringstream _spacer;
0599 _filler.fill('#');
0600 _filler << std::setw((G4int)_msg.length()) << "";
0601 _spacer << std::setw(10) << "";
0602 std::cout << "\n\n"
0603 << _spacer.str() << _filler.str() << "\n"
0604 << _spacer.str() << _msg << "\n"
0605 << _spacer.str() << _filler.str() << "\n\n"
0606 << std::flush;
0607 }
0608 _first = false;
0609 G4int cnt = 0;
0610 for(auto& itr : _signals)
0611 {
0612 if(itr < 0)
0613 continue;
0614 if(GetData().is_active[itr])
0615 continue;
0616 ++cnt;
0617 sigfillset(&(GetData().current[itr].sa_mask));
0618 sigdelset(&(GetData().current[itr].sa_mask), itr);
0619 GetData().current[itr].sa_sigaction = &Handler;
0620 GetData().current[itr].sa_flags = SA_SIGINFO;
0621 sigaction(itr, &(GetData().current[itr]), &(GetData().previous[itr]));
0622 }
0623 return cnt;
0624 }
0625
0626
0627
0628 inline G4int G4Backtrace::Enable(const std::string& _signals)
0629 {
0630 if(_signals.empty())
0631 return 0;
0632
0633 auto _add_signal = [](std::string sig, signal_set_t& _targ) {
0634 if(!sig.empty())
0635 {
0636 for(auto& itr : sig)
0637 itr = (char)std::toupper(itr);
0638 _targ.insert(G4Backtrace::GetSignal(sig));
0639 }
0640 };
0641
0642 const std::regex wsp_re("[ ,;:\t\n]+");
0643 auto _maxid = GetData().identifiers.size();
0644 auto _result = std::vector<std::string>(_maxid, "");
0645 std::copy(
0646 std::sregex_token_iterator(_signals.begin(), _signals.end(), wsp_re, -1),
0647 std::sregex_token_iterator(), _result.begin());
0648 signal_set_t _sigset{};
0649 for(auto& itr : _result)
0650 _add_signal(itr, _sigset);
0651 return Enable(_sigset);
0652 }
0653
0654
0655
0656 inline G4int G4Backtrace::Disable(signal_set_t _signals)
0657 {
0658 if(_signals.empty())
0659 {
0660 for(auto& itr : GetData().is_active)
0661 _signals.insert(itr.first);
0662 }
0663
0664 G4int cnt = 0;
0665 for(auto& itr : _signals)
0666 {
0667 if(itr < 0)
0668 continue;
0669 if(!GetData().is_active[itr])
0670 continue;
0671 ++cnt;
0672 sigaction(itr, &(GetData().previous[itr]), nullptr);
0673 GetData().current.erase(itr);
0674 GetData().is_active[itr] = false;
0675 }
0676 return cnt;
0677 }
0678
0679
0680
0681 inline G4int G4Backtrace::GetSignal(const std::string& sid)
0682 {
0683 for(auto&& itr : GetData().identifiers)
0684 {
0685 if(std::get<0>(itr) == sid)
0686 return std::get<1>(itr);
0687 }
0688 return -1;
0689 }
0690
0691
0692
0693 inline std::string G4Backtrace::Description(G4int sig)
0694 {
0695 for(auto&& itr : GetData().identifiers)
0696 {
0697 if(std::get<1>(itr) == sig)
0698 {
0699 std::stringstream ss;
0700 ss << " signal = " << std::setw(8) << std::get<0>(itr)
0701 << ", value = " << std::setw(4) << std::get<1>(itr)
0702 << ", description = " << std::get<2>(itr);
0703 return ss.str();
0704 }
0705 }
0706 std::stringstream ss;
0707 ss << " signal = " << std::setw(8) << "unknown"
0708 << ", value = " << std::setw(4) << sig;
0709 return ss.str();
0710 }
0711
0712
0713
0714 #else
0715
0716 # include <array>
0717 # include <functional>
0718 # include <map>
0719 # include <set>
0720 # include <string>
0721 # include <tuple>
0722 # include <vector>
0723
0724
0725 class G4Backtrace
0726 {
0727 public:
0728 struct fake_siginfo
0729 {};
0730 struct fake_sigaction
0731 {};
0732
0733 using siginfo_t = fake_siginfo;
0734 using sigaction_t = fake_sigaction;
0735 using exit_action_t = std::function<void(G4int)>;
0736 using frame_func_t = std::function<G4String(const char*)>;
0737 using signal_set_t = std::set<G4int>;
0738
0739 public:
0740 struct actions
0741 {
0742 using id_entry_t = std::tuple<std::string, G4int, std::string>;
0743 using id_list_t = std::vector<id_entry_t>;
0744
0745 std::map<G4int, G4bool> is_active = {};
0746 std::map<G4int, sigaction_t> current = {};
0747 std::map<G4int, sigaction_t> previous = {};
0748 std::vector<exit_action_t> exit_actions = {};
0749 const id_list_t identifiers = {};
0750 };
0751
0752 public:
0753 static void Handler(G4int, siginfo_t*, void*) {}
0754 static void Message(G4int, siginfo_t*, std::ostream&) {}
0755 static void ExitAction(G4int) {}
0756 static G4int Enable(const std::string&) { return 0; }
0757 static G4int Enable(const signal_set_t& = DefaultSignals()) { return 0; }
0758 static G4int Disable(signal_set_t = {}) { return 0; }
0759 static G4int GetSignal(const std::string&) { return -1; }
0760 static std::string Description(G4int) { return std::string{}; }
0761
0762 template <typename FuncT>
0763 static void AddExitAction(FuncT&&)
0764 {}
0765
0766 template <std::size_t Depth, std::size_t Offset = 0, typename FuncT = frame_func_t>
0767 static std::array<G4ResultOf_t<FuncT, const char*>, Depth> GetMangled(
0768 FuncT&& func = FrameFunctor())
0769 {
0770 using type = G4ResultOf_t<FuncT, const char*>;
0771 auto ret = std::array<type, Depth>{};
0772 ret.fill(func(""));
0773 return ret;
0774 }
0775
0776 template <std::size_t Depth, std::size_t Offset = 0, typename FuncT = frame_func_t>
0777 static std::array<G4ResultOf_t<FuncT, const char*>, Depth> GetDemangled(
0778 FuncT&& func = FrameFunctor())
0779 {
0780 using type = G4ResultOf_t<FuncT, const char*>;
0781 auto ret = std::array<type, Depth>{};
0782 ret.fill(func(""));
0783 return ret;
0784 }
0785
0786
0787 static frame_func_t& FrameFunctor()
0788 {
0789 static frame_func_t _instance = [](const char* _s) { return G4String(_s); };
0790 return _instance;
0791 }
0792
0793
0794 static signal_set_t& DefaultSignals()
0795 {
0796 static signal_set_t _instance = {};
0797 return _instance;
0798 }
0799
0800 static actions& GetData()
0801 {
0802 static auto _instance = actions{};
0803 return _instance;
0804 }
0805 };
0806
0807
0808
0809 #endif
0810 #endif