Bug 119289 - C++ throw/catch segfaults
Summary: C++ throw/catch segfaults
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: sparc64 (show other bugs)
Version: Unspecified
Hardware: Any Any
: Normal Affects Only Me
Assignee: Marius Strobl
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2008-01-03 03:40 UTC by Stephen Hurd
Modified: 2008-04-21 21:57 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Stephen Hurd freebsd_committer freebsd_triage 2008-01-03 03:40:01 UTC
Even the most simple trow/catch programs appear to crash in the __cxa_* functions.  this appears to be at least part of the problem with OpenEXR.

How-To-Repeat: The following simple program crashes with the following backtrace:

(gdb) r
Starting program: /home/admin/a.out 
start
Inside try block
Caught an exception -- value is: 99

Program received signal SIGSEGV, Segmentation fault.
0x0000000040396aac in __cxa_end_catch () from /usr/lib/libstdc++.so.6
(gdb) bt
#0  0x0000000040396aac in __cxa_end_catch () from /usr/lib/libstdc++.so.6
#1  0x0000000000100f38 in main () at test.cpp:13


// A simple exception handling example.
#include <iostream>
int main()
{
  std::cout << "start\n";
try
{   // start a try block
    std::cout << "Inside try block\n";
    throw 99; // throw an error
    std::cout << "This will not execute";
  }

catch (int i)
 {   // catch an error
    std::cout << "Caught an exception -- value is: ";
    std::cout << i << "\n";
  }

  std::cout << "end";

  return 0;
}
Comment 1 marius 2008-01-03 18:39:30 UTC
On Thu, Jan 03, 2008 at 03:29:48AM +0000, Stephen Hurd wrote:
> 
> Even the most simple trow/catch programs appear to crash in the __cxa_* functions.  this appears to be at least part of the problem with OpenEXR.
> >How-To-Repeat:
> The following simple program crashes with the following backtrace:
> 
> (gdb) r
> Starting program: /home/admin/a.out 
> start
> Inside try block
> Caught an exception -- value is: 99
> 
> Program received signal SIGSEGV, Segmentation fault.
> 0x0000000040396aac in __cxa_end_catch () from /usr/lib/libstdc++.so.6
> (gdb) bt
> #0  0x0000000040396aac in __cxa_end_catch () from /usr/lib/libstdc++.so.6
> #1  0x0000000000100f38 in main () at test.cpp:13
> 
> 
> // A simple exception handling example.
> #include <iostream>
> int main()
> {
>   std::cout << "start\n";
> try
> {   // start a try block
>     std::cout << "Inside try block\n";
>     throw 99; // throw an error
>     std::cout << "This will not execute";
>   }
> 
> catch (int i)
>  {   // catch an error
>     std::cout << "Caught an exception -- value is: ";
>     std::cout << i << "\n";
>   }
> 
>   std::cout << "end";
> 
>   return 0;
> }
> 

The underlying problem (from a libstdc++ perspective) is that with
GCC 4.2 __gthread_active_p() always returns 1, regardless of whether
the program was compiled with -pthread or not. This is even a MI
problem:

marius@alchemy:/home/marius > uname -a
FreeBSD alchemy.franken.de 8.0-CURRENT FreeBSD 8.0-CURRENT #0: Thu Dec  6 15:47:30 CET 2007     root@alchemy.franken.de:/tmp/obj/usr/src/sys/alchemy  i386
marius@alchemy:/home/marius > cat test.cc
#include <iostream>

int main()
{

	std::cout << "__gthread_active_p=" << __gthread_active_p() << "\n";
	return (0);
}
marius@alchemy:/home/marius > g++ -o test test.cc
marius@alchemy:/home/marius > ./test
__gthread_active_p=1
marius@alchemy:/home/marius > g++ -o test -pthread test.cc
marius@alchemy:/home/marius > ./test
__gthread_active_p=1


For reference, with GCC 3.4.6 on a FreeBSD 6.2-STABLE:

marius@vnv:/home/marius > uname -a
FreeBSD vnv.invalid 6.2-STABLE FreeBSD 6.2-STABLE #6: Wed Jun 13 09:21:13 CEST 2007     root@vnv.invalid:/usr/obj/usr/src/sys/vnv  i386
marius@vnv:/home/marius > cat test.cc
#include <iostream>

int main()
{

	std::cout << "__gthread_active_p=" << __gthread_active_p() << "\n";
	return (0);
}
marius@vnv:/home/marius > g++ -o test test.cc
marius@vnv:/home/marius > ./test
__gthread_active_p=0
marius@vnv:/home/marius > g++ -o test -pthread test.cc
marius@vnv:/home/marius > ./test
__gthread_active_p=1


With GCC 4.2 __gthread_active_p() always returning 1 breaks the
exception handling of libstdc++ for non-threaded programs on
platforms without TLS support due to the way it implements EH
there, i.e. on FreeBSD/arm and FreeBSD/sparc64 due to the lack
of TLS support for these archs in the ancient base binutils.
However, given that __gthread_active_p() is also used in a couple
of other places besides EH, this bug has great potential to also
cause problems in other areas and on all archs.

The reason for this false positive is that gthr-posix.h checks
for the existence of pthread_cancel() and FreeBSD 7 supplies
a stub for it in libc since lib/libc/gen/_pthread_stubs.c rev.
1.13. A solution for this is to use the __gthread_active_p()
version that libstdc++ uses for Solaris and which actively
checks for a working POSIX threads implementation (if such
functions exist) instead of checking for the mere existence
of corresponding functions. The patch below changes gthr-posix.h
accordingly (in order to use it it's probably best to go through
buildworld and installworld in order to ensure all base consumers
of gthr-posix.h are rebuilt and all copies of gthr-posix.h are
also updated).
Does anyone object to me committing that patch to the vendor
branch?

Marius

Index: gthr-posix.h
===================================================================
RCS file: /usr/data/bsd/cvs/fbsd/src/contrib/gcc/gthr-posix.h,v
retrieving revision 1.1.1.8
diff -u -r1.1.1.8 gthr-posix.h
--- gthr-posix.h	14 Aug 2007 02:37:31 -0000	1.1.1.8
+++ gthr-posix.h	3 Jan 2008 14:54:51 -0000
@@ -152,9 +152,13 @@
    it is passed so we cannot pretend that the interface is active if -pthreads
    is not specified.  On Solaris 2.5.1, the interface is not exposed at all so
    we need to play the usual game with weak symbols.  On Solaris 10 and up, a
-   working interface is always exposed.  */
+   working interface is always exposed.
+   On FreeBSD 6 and 7 the libc also exposes a dummy POSIX threads interface,
+   similar to what Solaris 2.6 up to 9 does.  FreeBSD >= 700014 even provides
+   a pthread_cancel stub in libc, which means the alternate __gthread_active_p
+   below can't be used there.  */
 
-#if defined(__sun) && defined(__svr4__)
+#if defined(__FreeBSD__) || (defined(__sun) && defined(__svr4__))
 
 static volatile int __gthread_active = -1;
 
@@ -197,7 +201,7 @@
   return __gthread_active_latest_value != 0;
 }
 
-#else /* not Solaris */
+#else /* neither FreeBSD nor Solaris */
 
 static inline int
 __gthread_active_p (void)
@@ -207,7 +211,7 @@
   return __gthread_active_ptr != 0;
 }
 
-#endif /* Solaris */
+#endif /* FreeBSD or Solaris */
 
 #else /* not SUPPORTS_WEAK */
Comment 2 David E. O'Brien freebsd_committer freebsd_triage 2008-01-04 03:32:55 UTC
On Thu, Jan 03, 2008 at 07:39:30PM +0100, Marius Strobl wrote:
> Does anyone object to me committing that patch to the vendor
> branch?

I'd rather not - unless it actually has been submitted upstream and there
was some indication the change was tolerable to the GCC folks (or its
clear they aren't working with us on a solution).

I do think it needs to get into RELENG_7_0 ASAP, though.  How about
committing it just to RELENG_7* for now?


 
> RCS file: /usr/data/bsd/cvs/fbsd/src/contrib/gcc/gthr-posix.h,v
..
>     we need to play the usual game with weak symbols.  On Solaris 10 and up, a
> -   working interface is always exposed.  */
> +   working interface is always exposed.
> +   On FreeBSD 6 and 7 the libc also exposes a dummy POSIX threads interface,
> +   similar to what Solaris 2.6 up to 9 does.  FreeBSD >= 700014 even provides
> +   a pthread_cancel stub in libc, which means the alternate __gthread_active_p
> +   below can't be used there.  */

If I may suggest the FSF-style formatting:

    we need to play the usual game with weak symbols.  On Solaris 10 and up, a
+   working interface is always exposed.  On FreeBSD 6 and later, libc also
+   exposes a dummy POSIX threads interface, similar to what Solaris 2.6 up
+   to 9 does.  FreeBSD >= 700014 even provides a pthread_cancel stub in libc,
+   which means the alternate __gthread_active_p below cannot be used there.  */

-- 
-- David  (obrien@FreeBSD.org)
Comment 3 dfilter service freebsd_committer freebsd_triage 2008-01-05 22:58:57 UTC
marius      2008-01-05 22:58:51 UTC

  FreeBSD src repository

  Modified files:        (Branch: RELENG_7)
    contrib/gcc          gthr-posix.h 
  Log:
  On FreeBSD GCC 4.2.x checks for the existence of pthread_cancel() in
  order to determine whether a program is running with multithreading
  support. This check causes __gthread_active_p() to always return 1
  however, regardless of whether the program was actually compiled with
  -pthread or not, due to the fact that the FreeBSD libc contains a
  pthread_cancel() stub. Fix this by using the __gthread_active_p()
  version that GCC uses for Solaris and which actively checks for a
  working POSIX threads implementation (if such functions exist) instead
  of checking for the mere existence of corresponding functions.
  
  On platforms without TLS support, i.e. on arm and sparc64 due to the
  lack of GNU TLS support for these archs in binutils 2.15., the false
  positives returned by __gthread_active_p() for non-threaded programs
  cause the exception handling implementation GCC uses in this case to
  crash. This is because GCC assumes that the POSIX threading functions
  actually work when __gthread_active_p() returns 1 while in fact the
  corresponding stubs in libc just immediately return.
  Given that __gthread_active_p() is also used in a couple of other
  places besides exception handling, this bug has great potential to
  also cause problems in other areas and on all archs.
  
  This is committed to RELENG_7 directly in order to get a fix into
  RELENG_7_0 as soon as possible while allowing to loop the official
  fix back into the vendor branch and not taking gthr-posix.h off the
  vendor branch in HEAD.
  
  PR:             119289
  Reviewed by:    obrien (plus style fix)
  Approved by:    re (kensmith)
  
  Revision     Changes    Path
  1.1.1.8.2.1  +7 -4      src/contrib/gcc/gthr-posix.h
_______________________________________________
cvs-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/cvs-all
To unsubscribe, send any mail to "cvs-all-unsubscribe@freebsd.org"
Comment 4 Mark Linimon freebsd_committer freebsd_triage 2008-02-29 02:10:05 UTC
State Changed
From-To: open->patched

marius, does this need to be MFCed to RELENG_6, or can it just be closed? 


Comment 5 Mark Linimon freebsd_committer freebsd_triage 2008-02-29 02:10:05 UTC
Responsible Changed
From-To: freebsd-sparc64->marius
Comment 6 marius 2008-03-01 14:56:41 UTC
On Fri, Feb 29, 2008 at 02:11:43AM +0000, linimon@FreeBSD.org wrote:
> 
> marius, does this need to be MFCed to RELENG_6, or can it just be closed?
> 

It doesn't need to be MFCed to RELENG_6, it's still a MI bug in
HEAD/8-CURRENT though. As indicated by obrien@ (see audit-trail),
the plan is to let it be fixed upstream first and then to loop
the official fix back into our vendor branch once core@ approved
it. Gerald@ is still working on the former.

Marius
Comment 7 Mark Linimon freebsd_committer freebsd_triage 2008-03-03 04:20:02 UTC
State Changed
From-To: patched->suspended

Does not need MFC to 6; does, however, need to be dealt with when the 
next upstream version is incorporated.
Comment 8 dfilter service freebsd_committer freebsd_triage 2008-04-21 21:40:53 UTC
marius      2008-04-21 20:40:43 UTC

  FreeBSD src repository

  src/contrib/gcc - Imported sources
  Update of /home/ncvs/src/contrib/gcc
  In directory repoman.freebsd.org:/tmp/cvs-serv38448
  
  Log Message:
  * gthr-posix.h (__gthread_active_p): Use the Solaris implementation
  for FreeBSD as well.
  
  This is the fix for __gthread_active_p() returning false positives
  which was committed as rev. 1.1.1.8.2.1 to RELENG_7 but now looped
  back to the vendor branch via the GCC repository and relicensed to
  be GPLv2 by me.
  Thanks go to gerald@ for getting the fix approved upstream and for
  committing to the GCC repository.
  
  PR:		119289
  Approved by:	core
  
  Status:
  
  Vendor Tag:	FSF
  Release Tags:	gcc_trunk_20080418_SVN134423
  		
  U src/contrib/gcc/gthr-posix.h
  
  No conflicts created by this import
  
_______________________________________________
cvs-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/cvs-all
To unsubscribe, send any mail to "cvs-all-unsubscribe@freebsd.org"
Comment 9 Marius Strobl freebsd_committer freebsd_triage 2008-04-21 21:56:51 UTC
State Changed
From-To: suspended->closed


Close; this PR has been fully dealt with.