On Sun, Oct 21, 2012 at 7:17 AM, Kirk, Benjamin (JSC-EG311) <span dir="ltr"><<a href="mailto:benjamin.kirk-1@nasa.gov" target="_blank">benjamin.kirk-1@nasa.gov</a>></span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div id=":2t3">Aside from the debugger, you can enable floating point exceptions at runtime if there is interest.<br></div></blockquote><div><br></div><div>Thanks for this. There is code for Linux (using feenableexcept) and a bunch of esoteric architectures in petsc/src/sys/error/fp.c, activated when you pass -fp_trap. It looks like the xmmintrin option there wasn't correct.</div>
<div><br></div><div>Also, I see that the specific cause of the exception is actually retained in si_code, but with a different set of macros (FPE_FLTDIV) than feenableexcept (FE_DIVBYZERO).</div><div><br></div><div>Satish and Barry, is there any rationale for still using signal(2), which has been deprecated since 1988, instead of sigaction()?</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div id=":2t3">
<br>
Below is the code we use on mac/linux in libMesh to honor --enable-fpe on the command line.  Note this was adapted from code originally provided from INL by the Moose team, so thanks really goes to them!  We prefer the feenableexcept() API on linux, but on the Mac you can get access to most of the exceptions through the MMX instruction set.<br>

<br>
Independent of the debugger it will still print the actual error and a stack trace, which is often good enough to know what happened.<br>
<br>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br>
<br>
// floating-point exceptions<br>
#ifdef LIBMESH_HAVE_FENV_H<br>
#  include <fenv.h><br>
#endif<br>
#ifdef LIBMESH_HAVE_XMMINTRIN_H<br>
#  include <xmmintrin.h><br>
#endif<br>
<br>
<br>
<br>
  /**<br>
   * Floating point exception handler -- courtesy of Cody Permann & MOOSE team<br>
   */<br>
  void libmesh_handleFPE(int /*signo*/, siginfo_t *info, void * /*context*/)<br>
  {<br>
    std::cout << std::endl;<br>
    std::cout << "Floating point exception signaled (";<br>
    switch (info->si_code)<br>
      {<br>
      case FPE_INTDIV: std::cerr << "integer divide by zero"; break;<br>
      case FPE_INTOVF: std::cerr << "integer overflow"; break;<br>
      case FPE_FLTDIV: std::cerr << "floating point divide by zero"; break;<br>
      case FPE_FLTOVF: std::cerr << "floating point overflow"; break;<br>
      case FPE_FLTUND: std::cerr << "floating point underflow"; break;<br>
      case FPE_FLTRES: std::cerr << "floating point inexact result"; break;<br>
      case FPE_FLTINV: std::cerr << "invalid floating point operation"; break;<br>
      case FPE_FLTSUB: std::cerr << "subscript out of range"; break;<br>
      }<br>
    std::cout << ")!" << std::endl;<br>
<br>
    std::cout << std::endl;<br>
    std::cout << "To track this down, compile debug version, start debugger, set breakpoint for 'libmesh_handleFPE' and run" << std::endl;<br>
    std::cout << "In gdb do:" << std::endl;<br>
    std::cout << "  break libmesh_handleFPE" << std::endl;<br>
    std::cout << "  run ..." << std::endl;<br>
    std::cout << "  bt" << std::endl;<br>
<br>
    libmesh_error();<br>
  }<br>
<br>
<br>
  /**<br>
   * Toggle floating point exceptions -- courtesy of Cody Permann & MOOSE team<br>
   */<br>
  void enableFPE(bool on)<br>
  {<br>
#if !defined(LIBMESH_HAVE_FEENABLEEXCEPT) && defined(LIBMESH_HAVE_XMMINTRIN_H)<br>
    static int flags = 0;<br>
#endif<br>
<br>
    if (on)<br>
      {<br>
        struct sigaction new_action, old_action;<br>
<br>
#ifdef LIBMESH_HAVE_FEENABLEEXCEPT<br>
        feenableexcept(FE_DIVBYZERO | FE_INVALID);<br>
#elif  LIBMESH_HAVE_XMMINTRIN_H<br>
        flags = _MM_GET_EXCEPTION_MASK();           // store the flags<br>
        _MM_SET_EXCEPTION_MASK(flags & ~_MM_MASK_INVALID);<br>
#endif<br>
<br>
<br>
        // Set up the structure to specify the new action.<br>
        new_action.sa_sigaction = libmesh_handleFPE;<br>
        sigemptyset (&new_action.sa_mask);<br>
        new_action.sa_flags = SA_SIGINFO;<br>
<br>
        sigaction (SIGFPE, NULL, &old_action);<br>
        if (old_action.sa_handler != SIG_IGN)<br>
          sigaction (SIGFPE, &new_action, NULL);<br>
      }<br>
    else<br>
      {<br>
#ifdef LIBMESH_HAVE_FEDISABLEEXCEPT<br>
        fedisableexcept(FE_DIVBYZERO | FE_INVALID);<br>
#elif  LIBMESH_HAVE_XMMINTRIN_H<br>
        _MM_SET_EXCEPTION_MASK(flags);<br>
#endif<br>
        signal(SIGFPE, 0);<br>
      }<br>
  }</div></blockquote></div><br>