This is the mail archive of the gcc-prs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

c++/661: -fsjlj-exceptions breaks programs using exception specifications



>Number:         661
>Category:       c++
>Synopsis:       -fsjlj-exceptions breaks programs using exception specifications
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    unassigned
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Oct 19 07:06:00 PDT 2000
>Closed-Date:
>Last-Modified:
>Originator:     Hugo Mildenberger
>Release:        2.95.2
>Organization:
>Environment:
gcc --version: 2.95.2
ld  --version: GNU ld 2.9.5
glibc-2.1.3, compiled with -fsjlj-exceptions -fasynchronous-exceptions
uname -r: (linux) 2.4.0-test8
cc: g++ -g -fsjlj-exceptions -fasynchronous-exceptions -lstd -o synce  synce.cc

>Description:
With -fsjlj-exceptions, the specification of thrown 
exception types in function definitions leads to program exit.  

This is related to the fact that __throw is called implicitely instead of __sjthrow while checking exception specification (since libgcc2.a is not compiled with -fsjlj-exceptions)

- maybe this would be fixed in this situation by compiling
  libgcc2 by -fsjlj-exceptions (breaking the 
   other exception implementation flavours though)?

 - maybe you need to emit a call to a specialized version of
   __check_eh_spec on -fsjlj-exceptions?

 - within exception.cc, part of libgcc2.a:
   extern "C" void
     __check_eh_spec (int n, const void **spec)
     {
       cp_eh_info *p = CP_EH_INFO;

       for (int i = 0; i < n; ++i)
         {
           if (__throw_type_match_rtti (spec[i]
                        , p->type, p->value))

  --THIS IS EVIL--->     throw;
  
         }

So it is obviously related to all programs using exception specification and -fsjlj-exceptions.  It does not depend from  -fasynchronous-exceptions and not from throwing within a signal handler. 
>How-To-Repeat:
// Description: With -fsjlj-exceptions, the specification of thrown 
// exception types in function definitions leads to program exit.  
//
// This is related to the fact that __throw is called implicitely 
// instead of __sjthrow while checking exception specification since
// libgcc2.a is not compiled with -fsjlj-exceptions 
//
// - maybe this would be fixed in this situation by compiling
//   libgcc2 by -fsjlj-exceptions (breaking the other exception implementation
//   flavours though)?
//
// - maybe you need to emit a call to a specialized version of
//   __check_eh_spec on -fsjlj-exceptions?
//
// - within exception.cc:
//   extern "C" void
//     __check_eh_spec (int n, const void **spec)
//     {
//       cp_eh_info *p = CP_EH_INFO;
//
//       for (int i = 0; i < n; ++i)
//         {
//           if (__throw_type_match_rtti (spec[i], p->type, p->value))
//
//  ----->     throw;
//  
//         }
//
// This is obviously related to all programs using exception 
// specification and -fsjlj-exceptions.  It does not depend from 
// -fasynchronous-exceptions and not from throwing within a signal
// handler. Indeed, you can omit -fasynchronous-exceptions for 
// same result. Or, as a proof, you can call simply call 
// throw_something() instead of generating a FPE in function test()
// which is done now as a default.
//
// Environment:
// gcc --version: 2.95.2
// ld  --version: GNU ld 2.9.5
// glibc-2.1.3, compiled with -fsjlj-exceptions -fasynchronous-exceptions
// uname -r: (linux) 2.4.0-test8
// cc:
// g++ -g -fsjlj-exceptions -fasynchronous-exceptions -lstd -o synce  synce.cc
//

#include <signal.h>
#include <memory.h>
#include <fenv.h>
#include <typeinfo>
#include <iostream>
#include <strstream>
#include <stdexcept>

void handler(int signal, siginfo_t *info, void * ucontext)  
{
     if (signal==SIGFPE)
         throw std::runtime_error("sigfpe"); 
}
void throw_something() 
{
    throw std::runtime_error("never call this a bug! This would be evil"); 
}

// Bug? You can not specify thrown exceptions or else program will be 
// aborted - but NOT by  __default_unexpected. 
// same behaviour for simple types, e.g. int  
void test(void) throw(std::runtime_error)
//void test(void) 
{
     try {
          double x=1;
          double y=0;

          throw_something();

          if (x/y);

     } catch(std::runtime_error  e) {
       cerr << __FUNCTION__ << " caught:<"  << e.what() << ">" << endl;
     
       throw e;
     }
}

void install_handler(int signal) 
{
  struct sigaction newhandler;
  memset(&newhandler,0,sizeof(newhandler));
  newhandler.sa_sigaction=handler;
  newhandler.sa_flags=SA_SIGINFO;
  if (int r = sigaction(signal,&newhandler,NULL)) { 
      strstream s;
      s << __FUNCTION__ << ": sigaction returned error status " 
           << strerror(r) << " (" << r <<")" << endl;
      throw std::runtime_error(s.str());
  }
}

void set_fpu_exception_mask(int mask) 
{
 fenv_t  env;
 fegetenv(&env);
 env.__control_word = ~mask;
 fesetenv(&env);	
}

int main() 
{

try {
       install_handler(SIGFPE);
       set_fpu_exception_mask(FE_ALL_EXCEPT&~FE_INEXACT);
       test();
 } catch (std::runtime_error e) {
   cerr << __FUNCTION__ << " caught:<"  << e.what() << ">" << endl;
 }

}
>Fix:
omit exception specification?
don't use -fsjlj-exceptions?
don't use -fasynchronous-exceptions?
don't use gcc?
>Release-Note:
>Audit-Trail:
>Unformatted:
----gnatsweb-attachment----
Content-Type: text/plain; name="SYNCE.CC"
Content-Disposition: inline; filename="SYNCE.CC"

// Description: With -fsjlj-exceptions, the specification of thrown 
// exception types in function definitions leads to program exit.  
//
// This is related to the fact that __throw is called implicitely 
// instead of __sjthrow while checking exception specification since
// libgcc2.a is not compiled with -fsjlj-exceptions 
//
// - maybe this would be fixed in this situation by compiling
//   libgcc2 by -fsjlj-exceptions (breaking the other exception implementation
//   flavours though)?
//
// - maybe you need to emit a call to a specialized version of
//   __check_eh_spec on -fsjlj-exceptions?
//
// - within exception.cc:
//   extern "C" void
//     __check_eh_spec (int n, const void **spec)
//     {
//       cp_eh_info *p = CP_EH_INFO;
//
//       for (int i = 0; i < n; ++i)
//         {
//           if (__throw_type_match_rtti (spec[i], p->type, p->value))
//
//  ----->     throw;
//  
//         }
//
// This is obviously related to all programs using exception 
// specification and -fsjlj-exceptions.  It does not depend from 
// -fasynchronous-exceptions and not from throwing within a signal
// handler. Indeed, you can omit -fasynchronous-exceptions for 
// same result. Or, as a proof, you can call simply call 
// throw_something() instead of generating a FPE in function test()
// which is done now as a default.
//
// Environment:
// gcc --version: 2.95.2
// ld  --version: GNU ld 2.9.5
// glibc-2.1.3, compiled with -fsjlj-exceptions -fasynchronous-exceptions
// uname -r: (linux) 2.4.0-test8
// cc:
// g++ -g -fsjlj-exceptions -fasynchronous-exceptions -lstd -o synce  synce.cc
//

#include <signal.h>
#include <memory.h>
#include <fenv.h>
#include <typeinfo>
#include <iostream>
#include <strstream>
#include <stdexcept>

void handler(int signal, siginfo_t *info, void * ucontext)  
{
     if (signal==SIGFPE)
         throw std::runtime_error("sigfpe"); 
}
void throw_something() 
{
    throw std::runtime_error("never call this a bug! This would be evil"); 
}

// Bug? You can not specify thrown exceptions or else program will be 
// aborted - but NOT by  __default_unexpected. 
// same behaviour for simple types, e.g. int  
void test(void) throw(std::runtime_error)
//void test(void) 
{
     try {
          double x=1;
          double y=0;

          throw_something();

          if (x/y);

     } catch(std::runtime_error  e) {
       cerr << __FUNCTION__ << " caught:<"  << e.what() << ">" << endl;
     
       throw e;
     }
}

void install_handler(int signal) 
{
  struct sigaction newhandler;
  memset(&newhandler,0,sizeof(newhandler));
  newhandler.sa_sigaction=handler;
  newhandler.sa_flags=SA_SIGINFO;
  if (int r = sigaction(signal,&newhandler,NULL)) { 
      strstream s;
      s << __FUNCTION__ << ": sigaction returned error status " 
           << strerror(r) << " (" << r <<")" << endl;
      throw std::runtime_error(s.str());
  }
}

void set_fpu_exception_mask(int mask) 
{
 fenv_t  env;
 fegetenv(&env);
 env.__control_word = ~mask;
 fesetenv(&env);	
}

int main() 
{

try {
       install_handler(SIGFPE);
       set_fpu_exception_mask(FE_ALL_EXCEPT&~FE_INEXACT);
       test();
 } catch (std::runtime_error e) {
   cerr << __FUNCTION__ << " caught:<"  << e.what() << ">" << endl;
 }

}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]