[ROOT] Need for SIGFPE emission on GNU/Linux.

From: Brett Viren (bv@bnl.gov)
Date: Thu May 22 2003 - 17:48:52 MEST


Hi Rene, Fons, Rooters,

As you may know, SIGFPE (floating point exception signals) are not
emitted by default on GCC/GLIBC GNU/Linux platforms.  They must be
turned on (see below) to catch things like overflows, divide by zero,
invalid FP number, etc.

We recently turned this on in our own code and it is catching many
problems, some merely anoying, but some real.  It also is catching
some (so far) trivial problems in ROOT proper (eg, creating a
TGDoubleSlider with fVmin == fVmax causes SIGFPE in
TGDoubleVSlider::DoRedraw).

To help find these problems and make ROOT better I would like to
suggest that the code below get added to ROOT and turned on by the
developers when testing.

I think that it should be turned off by default in production code as
it is almost guaranteed that folks have lurking SIGFPEs in their code
and they probably won't appreciate the rude awakening (although they
should!).  However, it would be nice to have its use triggered w/out
having to re-compile, eg via setting an environment variable.

The code is designed for GNU/Linux systems and I don't know how
portable it is, but since this platform is one of, if not the,
dominant platform it should be useful for many.

Thanks,
-Brett.

---------------------------------------------

// sigfpe.h - turn on SIGFPE emission.
// To use create a static instance:
//
// static sigfpe allow_sigfpe(true);
//
#ifndef SIGFPE_H
#define SIGFPE_H
#if defined(linux)        // Implicit g++ definition
#include <fpu_control.h>
#include <fenv.h>
#endif
struct sigfpe
{
  sigfpe(bool activate);
  ~sigfpe();
#if defined(linux)
#if defined(__GLIBC__)&&(__GLIBC__>2 || __GLIBC__==2 && __GLIBC_MINOR__>=1)
  fenv_t old_setting;
#else
  fpu_control_t old_setting;
#endif
#endif
  bool activate_;
                                                                                
  static bool validate();
};
#endif  // SIGFPE_H

---------------------------------------------

// sigfpe.cxx
#include "sigfpe.h"

sigfpe::sigfpe(bool a) : activate_(a)
{
    if(activate_==true) {
#if defined(linux)
#if defined(__GLIBC__)&&(__GLIBC__>2 || __GLIBC__==2 && __GLIBC_MINOR__>=1)
        fenv_t newval;
        fegetenv(&old_setting);
        fegetenv(&newval);
        newval.__control_word &= ~(FE_INVALID|FE_DIVBYZERO|FE_OVERFLOW);
        fesetenv(&newval);
#else
        old_setting = __fpu_control;
        fpu_control_t newval =
            old_setting & ~(
                _FPU_MASK_IM
                |_FPU_MASK_ZM
                |_FPU_MASK_OM
                );
        _FPU_SETCW(newval);
#endif
#endif
    }
}
sigfpe::~sigfpe()
{
#if defined(linux)
    if(activate_==true)
#if defined(__GLIBC__)&&(__GLIBC__>2 || __GLIBC__==2 && __GLIBC_MINOR__>=1)
        fesetenv(&old_setting);
#else
       _FPU_SETCW(old_setting);
#endif
#endif
}
// end sigfpe.cxx

---------------------------------------------



This archive was generated by hypermail 2b29 : Thu Jan 01 2004 - 17:50:11 MET