[petsc-users] [petsc-maint #136411] PETSc Execution Error

Kirk, Benjamin (JSC-EG311) benjamin.kirk-1 at nasa.gov
Sun Oct 21 07:17:04 CDT 2012


On Oct 20, 2012, at 10:55 PM, Jed Brown <jedbrown at mcs.anl.gov> wrote:

> On Wed, Oct 17, 2012 at 1:45 PM, Barry Smith <bsmith at mcs.anl.gov> wrote:
> 
>     Paul,
> 
>     With this type of problem you need to get a handle on exactly where the floating point exception appeared.   This is done by running the debug version of the code in a debugger and asking the debugger to catch floating point exceptions (how to do this depends on the debugger). Once you see exactly where the floating point except ion comes from (for example a divide by zero, square root of a negative number etc) that can lead to seeing how to avoid it.
> 
>    Note to developers, we should have an answer for this in PETSc FAQ.
> 
> https://bitbucket.org/petsc/petsc-dev/changeset/6e2912899260e1c94b78c60754198048af02ca85
> 
> Can one of you Mac users figure out how to make -fp_trap work there?

Aside from the debugger, you can enable floating point exceptions at runtime if there is interest. 

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.

Independent of the debugger it will still print the actual error and a stack trace, which is often good enough to know what happened.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

// floating-point exceptions
#ifdef LIBMESH_HAVE_FENV_H
#  include <fenv.h>
#endif
#ifdef LIBMESH_HAVE_XMMINTRIN_H
#  include <xmmintrin.h>
#endif



  /**
   * Floating point exception handler -- courtesy of Cody Permann & MOOSE team
   */
  void libmesh_handleFPE(int /*signo*/, siginfo_t *info, void * /*context*/)
  {
    std::cout << std::endl;
    std::cout << "Floating point exception signaled (";
    switch (info->si_code)
      {
      case FPE_INTDIV: std::cerr << "integer divide by zero"; break;
      case FPE_INTOVF: std::cerr << "integer overflow"; break;
      case FPE_FLTDIV: std::cerr << "floating point divide by zero"; break;
      case FPE_FLTOVF: std::cerr << "floating point overflow"; break;
      case FPE_FLTUND: std::cerr << "floating point underflow"; break;
      case FPE_FLTRES: std::cerr << "floating point inexact result"; break;
      case FPE_FLTINV: std::cerr << "invalid floating point operation"; break;
      case FPE_FLTSUB: std::cerr << "subscript out of range"; break;
      }
    std::cout << ")!" << std::endl;
    
    std::cout << std::endl;
    std::cout << "To track this down, compile debug version, start debugger, set breakpoint for 'libmesh_handleFPE' and run" << std::endl;
    std::cout << "In gdb do:" << std::endl;
    std::cout << "  break libmesh_handleFPE" << std::endl;
    std::cout << "  run ..." << std::endl;
    std::cout << "  bt" << std::endl;
    
    libmesh_error();
  }


  /**
   * Toggle floating point exceptions -- courtesy of Cody Permann & MOOSE team
   */
  void enableFPE(bool on)
  {
#if !defined(LIBMESH_HAVE_FEENABLEEXCEPT) && defined(LIBMESH_HAVE_XMMINTRIN_H)
    static int flags = 0;
#endif
    
    if (on)
      {
        struct sigaction new_action, old_action;
        
#ifdef LIBMESH_HAVE_FEENABLEEXCEPT
        feenableexcept(FE_DIVBYZERO | FE_INVALID);
#elif  LIBMESH_HAVE_XMMINTRIN_H
        flags = _MM_GET_EXCEPTION_MASK();           // store the flags
        _MM_SET_EXCEPTION_MASK(flags & ~_MM_MASK_INVALID);
#endif
        

        // Set up the structure to specify the new action.
        new_action.sa_sigaction = libmesh_handleFPE;
        sigemptyset (&new_action.sa_mask);
        new_action.sa_flags = SA_SIGINFO;
        
        sigaction (SIGFPE, NULL, &old_action);
        if (old_action.sa_handler != SIG_IGN)
          sigaction (SIGFPE, &new_action, NULL);
      }
    else
      {
#ifdef LIBMESH_HAVE_FEDISABLEEXCEPT
        fedisableexcept(FE_DIVBYZERO | FE_INVALID);
#elif  LIBMESH_HAVE_XMMINTRIN_H
        _MM_SET_EXCEPTION_MASK(flags);
#endif
        signal(SIGFPE, 0);
      }
  }
  



More information about the petsc-users mailing list