Back to home page

EIC code displayed by LXR

 
 

    


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