This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
c++/661: -fsjlj-exceptions breaks programs using exception specifications
- To: gcc-gnats at gcc dot gnu dot org
- Subject: c++/661: -fsjlj-exceptions breaks programs using exception specifications
- From: Hugo dot Mildenberger at topmail dot de
- Date: 19 Oct 2000 14:00:52 -0000
- Reply-To: Hugo dot Mildenberger at topmail dot de
- Resent-Cc: gcc-prs at gcc dot gnu dot org, gcc-bugs at gcc dot gnu dot org, jason at gcc dot gnu dot org
- Resent-Reply-To: gcc-gnats@gcc.gnu.org, Hugo.Mildenberger@topmail.de
>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;
}
}