![]() |
|
|||
File indexing completed on 2025-09-16 09:03:48
0001 // PythiaFpe.h is a part of the PYTHIA event generator. 0002 // Copyright (C) 2025 Christian Bierlich and Torbjorn Sjostrand. 0003 // PYTHIA is licenced under the GNU GPL v2 or later, see COPYING for details. 0004 // Please respect the MCnet Guidelines, see GUIDELINES for details. 0005 0006 // Definition of behaviour for debugging flag -DGCCFPDEBUG. This 0007 // snippet should, when enabled, cause programs to fail at runtime if 0008 // they contain a floating point exception. Note that underflow and 0009 // inexact are not caught, see comment in raisefpe() to enable 0010 // them. This is not recommended, as FE_UNDERFLOW would also catch 0011 // things like small exponents, and FE_INEXACT would catch things like 0012 // 1.0 / 3.0. Expected output is "Caught SIGFPE (Floating Point 0013 // Exception)" followed by a stack trace. The program will exit with 0014 // error. Note that this behaviour is both compiler dependent and 0015 // platform dependent. It works only with gcc on x86/x86_64 (with 0016 // SSE). On other platforms (ARM, PPC, etc.), SSE intrinsics won't be 0017 // valid. This includes x86_64 emulated on ARM e.g. in docker. 0018 0019 // Run ./configure with --obj-common=-DGCCFPDEBUG to enable. 0020 // For better stack trace symbols add -O0 -g -rdynamic: 0021 // --obj-common='-g -O0 -rdynamic -DGCCFPDEBUG' 0022 // Consider also -lexecinfo (if you see "undefined reference to 0023 // backtrace...") and -fno-omit-frame-pointer. 0024 // Should never be combined with compile flags such as: 0025 // -ffast-math -Ofast -fno-trapping-math 0026 // or other fast math flags, as they may optimize away the 0027 // trapping. 0028 0029 #ifndef Pythia8_PythiaFpe_H 0030 #define Pythia8_PythiaFpe_H 0031 0032 // Check the GCCFPDEBUG flag. 0033 #ifdef GCCFPDEBUG 0034 0035 // Catch compilation on ARM platforms. 0036 #ifdef __aarch64__ 0037 #error "GCCDEBUG unsupported on ARM64. Disable -DGCCDEBUG or compile on x86." 0038 #endif 0039 0040 #ifndef __ENABLE_FP_DEBUG__ 0041 #define __ENABLE_FP_DEBUG__ 0042 #include <csignal> // Provides sigaction, siginfo_t. 0043 #include <fenv.h> // Provides feenableexcept(). 0044 #include <xmmintrin.h> // Provides _MM_GET/SET_EXCEPTION_MASK(). 0045 #include <execinfo.h> // Provides backtrace(), backtrace_symbols_fd(). 0046 #include <unistd.h> // Provides STDERR_FILENO. 0047 0048 // Implement a signal handler. This will catch the action raised by 0049 // the FPE trigger, print a stack trace and exit. This makes it easier 0050 // to find the location in the code where the FPE happened. Handle 0051 // the signal. 0052 static void fpeSignalHandler(int sig, siginfo_t* info, void* context) { 0053 0054 // Suppress compiler warnings from -Wunused-parameter. 0055 (void)sig; 0056 (void)info; 0057 (void)context; 0058 0059 // Print an error message. Avoid C++ I/O for async safety. 0060 fprintf(stderr, "\n*************************************************\n"); 0061 fprintf(stderr, "** Caught SIGFPE (Floating Point Exception) **\n"); 0062 fprintf(stderr, "** Printing stack trace (compile with -O0 -g) **\n"); 0063 fprintf(stderr, "** For better symbols, also consider -rdynamic.**\n"); 0064 fprintf(stderr, "*************************************************\n"); 0065 0066 // Obtain a backtrace. 0067 void* buffer[32]; 0068 int n = backtrace(buffer, 32); 0069 0070 // Print the backtrace. 0071 backtrace_symbols_fd(buffer, n, STDERR_FILENO); 0072 fprintf(stderr, "*************************************************\n"); 0073 0074 // Exit with error. Use low-level _exit to avoid calling destructors. 0075 _exit(1); 0076 0077 } 0078 0079 // Setup a handler to catch the signal allowing an action before the 0080 // program exits. 0081 static void __attribute__((constructor)) setupFpeHandler() { 0082 0083 // Setup a sigaction for the handler. 0084 struct sigaction sa; 0085 // Define the action. 0086 sa.sa_sigaction = fpeSignalHandler; 0087 // Empty the handler. 0088 sigemptyset(&sa.sa_mask); 0089 // Set the action we want: siginfo_t 0090 sa.sa_flags = SA_SIGINFO; 0091 // Install the handler 0092 sigaction(SIGFPE, &sa, nullptr); 0093 0094 } 0095 0096 // Enable raising of the FPE by unmasking FPU exceptions. This 0097 // includes both x87 FPU (feenableexcept) and SSE exceptions. 0098 static void __attribute__((constructor)) raisefpe() { 0099 0100 // Enable x87 FPU exceptions. To catch all exceptions, add 0101 // FE_UNDERFLOW and FE_INEXACT. 0102 feenableexcept (FE_DIVBYZERO | FE_OVERFLOW | FE_INVALID); 0103 0104 // Enable SSE exceptions. To catch all exceptions, add 0105 // _MM_MASK_UNDERFLOW and _MM_MASK_INEXACT. 0106 unsigned int cw = _MM_GET_EXCEPTION_MASK(); 0107 cw &= ~(_MM_MASK_DIV_ZERO | _MM_MASK_INVALID | _MM_MASK_OVERFLOW); 0108 _MM_SET_EXCEPTION_MASK(cw); 0109 0110 } 0111 0112 //========================================================================== 0113 0114 #endif // GCCFPDEBUG 0115 0116 #endif // __ENABLE_FP_DEBUG__ 0117 0118 #endif // Pythia8_PythiaFpe_H
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |