From owner-freebsd-sparc64@FreeBSD.ORG Thu Jan 3 19:00:10 2008 Return-Path: Delivered-To: freebsd-sparc64@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 541F916A46C for ; Thu, 3 Jan 2008 19:00:10 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 4455713C47E for ; Thu, 3 Jan 2008 19:00:10 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.14.2/8.14.2) with ESMTP id m03J09Ct059287 for ; Thu, 3 Jan 2008 19:00:09 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.2/8.14.1/Submit) id m03J09oh059286; Thu, 3 Jan 2008 19:00:09 GMT (envelope-from gnats) Date: Thu, 3 Jan 2008 19:00:09 GMT Message-Id: <200801031900.m03J09oh059286@freefall.freebsd.org> To: freebsd-sparc64@FreeBSD.org From: Marius Strobl Cc: Subject: Re: sparc64/119289: C++ throw/catch segfaults X-BeenThere: freebsd-sparc64@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: Marius Strobl List-Id: Porting FreeBSD to the Sparc List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 03 Jan 2008 19:00:10 -0000 The following reply was made to PR sparc64/119289; it has been noted by GNATS. From: Marius Strobl To: bug-followup@FreeBSD.org, Stephen Hurd , kan@FreeBSD.org, obrien@FreeBSD.org Cc: re@FreeBSD.org Subject: Re: sparc64/119289: C++ throw/catch segfaults Date: Thu, 3 Jan 2008 19:39:30 +0100 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 > 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 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 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 */