Bug 82081

Summary: libstdc++ SIGABRT when throwing exceptions
Product: [Retired] Red Hat Raw Hide Reporter: tanner
Component: gccAssignee: Jakub Jelinek <jakub>
Status: CLOSED NOTABUG QA Contact: David Lawrence <dkl>
Severity: medium Docs Contact:
Priority: medium    
Version: 1.0   
Target Milestone: ---   
Target Release: ---   
Hardware: i386   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2004-11-24 14:29:14 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 79579, 100644    

Description tanner 2003-01-17 07:09:10 UTC
Program received signal SIGABRT, Aborted.
[Switching to Thread 8192 (LWP 2294)]
0x408e7921 in kill () from /lib/libc.so.6
(gdb) bt
#0  0x408e7921 in kill () from /lib/libc.so.6
#1  0x406dc2aa in pthread_kill () from /lib/libpthread.so.0
#2  0x406dc591 in raise () from /lib/libpthread.so.0
#3  0x408e8808 in abort () from /lib/libc.so.6
#4  0x4086ffb7 in __cxxabiv1::__terminate(void (*)()) (
    handler=0x408e868c <abort>)
    at ../../../../libstdc++-v3/libsupc++/eh_terminate.cc:47
#5  0x40870004 in std::terminate() ()
    at ../../../../libstdc++-v3/libsupc++/eh_terminate.cc:57
#6  0x40870176 in __cxa_throw ()
    at ../../../../libstdc++-v3/libsupc++/eh_throw.cc:77
#7  0x4003aba8 in com_uwyn_qtunit::TestCase::assertImpl(QString const&, bool,
QString const&, long) (this=0x806a9dc, rConditionExpr=@0xbfffe980,
    condition=false, rFileName=@0xbfffea00, lineNumber=89)
    at framework/TestCase.cpp:106
#8  0x4003ace7 in com_uwyn_qtunit::TestCase::assertTrue(QString const&, bool,
char const*, QString const&, long) (this=0x806a9dc, rConditionExpr=@0xbfffea10,
    condition=false, pMessage=0x0, rFileName=@0xbfffea00, lineNumber=89)
    at framework/TestCase.cpp:118
#9  0x4009d376 in com_uwyn_qtunit::ExampleTestCase::testSetUp() (
    this=0x806a9dc) at ExampleTestCase.cpp:89
#10 0x4009d666 in com_uwyn_qtunit::Test<com_uwyn_qtunit::ExampleTestCase>::run()
const (this=0x804e9c8) at ../../src/framework/Test.h:63
#11 0x40043aca in
com_uwyn_qtunit::TestRunner::runTest(com_uwyn_qtunit::TestBase const&)
(this=0xbfffec70, rTest=@0x804e9c8) at framework/TestRunner.cpp:78
#12 0x400468ec in com_uwyn_qtunit::TextTestRunner::run() (this=0xbfffec70)
    at textrunner/TextTestRunner.cpp:110
#13 0x08048741 in main (argc=2, argv=0xbfffed74) at SampleTextRunner.cpp:39
#14 0x408d653d in __libc_start_main () from /lib/libc.so.6

Comment 1 tanner 2003-01-17 22:56:49 UTC
Upgraded to gcc-3.2.1 20021207 and still get the SIGABRT problem.

Comment 2 Jakub Jelinek 2003-01-17 23:05:26 UTC
abort () is the default __terminate() implementation.
You should find out why the exception has not been caught.

Comment 3 tanner 2003-01-17 23:11:51 UTC
Just to make sure I understand you. You are saying this looks like a problem in
the -application- not catching an exception?



Comment 4 Jakub Jelinek 2003-01-17 23:14:59 UTC
It is VERY likely a bug in the application (of course, unless you prove that
there is a catch block which accepts that exception).

Comment 5 tanner 2003-01-17 23:19:19 UTC
I'll double check the code tonight to verify. I seem to remember seeing

catch (...) block, but I'll confirm tonight after my "real" job.

Comment 6 tanner 2003-01-20 03:34:54 UTC
Breaking down gdb backtrace, I'm still of the opinion that there is a problem
with exception handling in libstdc++, all this code is open source and can be
gotten from http://www.uwyn.com/projects/qtunit/


#13 0x08048741 in main (argc=2, argv=0xbfffed74) at SampleTextRunner.cpp:39
int main(int argc, char **argv)
{
        cout << "Debugging" << flush;
        TextTestRunner runner(argc, argv);

        runner.run();   // Line 39

        return 0;
}


#12 0x400468ec in com_uwyn_qtunit::TextTestRunner::run() (this=0xbfffec70)
    at textrunner/TextTestRunner.cpp:110
void TextTestRunner::run()
{
<snip>
                        runTest(*it.current());
}

#11 0x40043aca in
com_uwyn_qtunit::TestRunner::runTest(com_uwyn_qtunit::TestBase const&)
(this=0xbfffec70, rTest=@0x804e9c8) at framework/TestRunner.cpp:78

Here is where the catch block starts:

        try {
                rTest.run();
                mpResult->addSuccess(new
TestDescription(rTest.testCase().lastFileName(),
rTest.testCase().lastLineNumber(), rTest.testFullName()));
        } catch (QtUnitException& rException) {
                // handle the exception
        }

Note that a QtUnitException is caught in this block.

#10 0x4009d666 in com_uwyn_qtunit::Test<com_uwyn_qtunit::ExampleTestCase>::run()
const (this=0x804e9c8) at ../../src/framework/Test.h:63
	template <class Fixture> void Test<Fixture>::run() const
	{
		(static_cast<Fixture*>(mpTestCase)->*mpTestMethod)();
	}

#9  0x4009d376 in com_uwyn_qtunit::ExampleTestCase::testSetUp() (
    this=0x806a9dc) at ExampleTestCase.cpp:89

void ExampleTestCase::testSetUp()
{
	double result = mValue1 + mValue2;
	qassertTrue(result == 5.0);
	qassertTrue(result == 6.0); // Line 89
}

#8  0x4003ace7 in com_uwyn_qtunit::TestCase::assertTrue(QString const&, bool,
char const*, QString const&, long) (this=0x806a9dc, rConditionExpr=@0xbfffea10,
    condition=false, pMessage=0x0, rFileName=@0xbfffea00, lineNumber=89)
    at framework/TestCase.cpp:118
void TestCase::assertTrue(const QString& rConditionExpr, bool condition, const
char* pMessage, const QString& rFileName, long lineNumber)
{ 
	QString message;

	if (NULL != pMessage)
	{
		message = QString(pMessage)+" : ";
	}
	assertImpl(message+notTrueMessage(rConditionExpr), condition, rFileName,
lineNumber);
}

#7  0x4003aba8 in com_uwyn_qtunit::TestCase::assertImpl(QString const&, bool,
QString const&, long) (this=0x806a9dc, rConditionExpr=@0xbfffe980,
condition=false, rFileName=@0xbfffea00, lineNumber=89) at framework/TestCase.cpp:106

Here is where the throw happens.

void TestCase::assertImpl(const QString& rConditionExpr, bool condition, const
QString& rFileName, long lineNumber)
{
        lastFileName(rFileName);
        mLastLineNumber = lineNumber;

        if (false == condition)
        {
                throw QtUnitException(rConditionExpr); // throw!
        }
}

I believe the catch in frame 11 in the method runTest should catch the
QtUnitException thrown above.

Download qtunit, make, then run it's own testsuite to simulate this error.


Comment 7 tanner 2003-01-20 05:37:24 UTC
From the author of qtunit:

TestCase.cpp:106 says :

throw QtUnitException(rConditionExpr);

This is the default assertion implementation which can be used by each
TestCase test method. This method is called by the Test fixture which
is instantiated when using the addTest macros (TestCase.h:41). When
run() is called below for each TestCase method and an assertion is
evaluated, a QtUnitException exception is thrown. This one should
bubble through until the try ... catch below. Any std exception class
is also catched to provide error-reporting on top of failure reporting
(catch (std::exception& rException)), and finally *ANY* other exception
type is caught (catch (...)), also for error reporting.

TestRunner.cpp:71-87 says :
try
{
        rTest.run();
        mpResult->addSuccess(new
TestDescription(rTest.testCase().lastFileName(),
                rTest.testCase().lastLineNumber(), rTest.testFullName()));
}
catch (QtUnitException& rException)
{
        mpResult->addFailure(new
TestDescription(rTest.testCase().lastFileName(),
                rTest.testCase().lastLineNumber(), rTest.testFullName(),
rException.what(), rTest.sourcePath()));
}
catch (std::exception& rException)
{
        mpResult->addError(new
TestDescription(rTest.testCase().lastFileName(), 0,
rTest.testFullName(),
                rException.what(), rTest.sourcePath()));
}
catch (...)
{
        mpResult->addError(new
TestDescription(rTest.testCase().lastFileName(), 0,
rTest.testFullName(),
                trUtf8("<unknown>"), rTest.sourcePath()));
}

This should catch *ALL* exceptions, categorised according to the amount
of feedback that can be given and the type of exceptional behaviour.

I have noticed (as said before) that gcc is however very picky about
its exception implementation and the correct header files should be
included in all related files before exceptions start bubbling up
correctly. If this is not done properly, abort() is called when 'scope
boundaries' are reached (for example the boundaries of a TestModule
share library). It's possible that in untested version numbers that has
changed and that the bubbling doesn't work correctly anymore. 

Comment 8 tanner 2003-01-20 05:38:45 UTC
I added std::set_terminate (__gnu_cxx::__verbose_terminate_handler);	
as recommended by 

http://gcc.gnu.org/onlinedocs/libstdc++/19_diagnostics/howto.html#1

terminate called after throwing a `com_uwyn_qtunit::QtUnitException'
  what(): result == 6.0 was not true


Comment 9 Ulrich Drepper 2004-09-28 06:24:26 UTC
This has nothing to do with glibc.  Reassign to gcc.  But they will
likely close the bug unless some recent testing is done.

Comment 10 Benjamin Kosnik 2004-10-01 17:15:01 UTC
Can't really tell what's going on without a self-contained test case,
sorry. 

Off hand, this may be caused by two live exceptions at once, at which
point unexpected is called. You can check this by creating an
unexpected handler, similar to the set_terminate call in comment 8. If
you create this, say something that prints out "unexpected" and then
calls the __verbose_terminate_handler, you'll be able to check if this
is the case.

That will at least tell you if the problem is within this app or gcc.

best,
benjamin

Comment 11 Jakub Jelinek 2004-11-24 14:29:14 UTC
If you have a self-contained testcase, please reopen.