Bug 54267

Summary: std::exception not catched when -O3 (-Os is fine, link static, FreeBSD 9.0-RELEASE-p3)
Product: gcc Reporter: David Keller <david.keller>
Component: targetAssignee: Not yet assigned to anyone <unassigned>
Status: UNCONFIRMED ---    
Severity: normal Keywords: EH
Priority: P3    
Version: 4.8.0   
Target Milestone: ---   
Host: Target: x68_64-freebsd*
Build: Known to work:
Known to fail: 4.7.2, 4.8.0 Last reconfirmed:
Attachments: Here is the faulty code.

Description David Keller 2012-08-15 02:01:24 UTC
1 #include <iostream>
  2 #include <boost/asio.hpp>
  3
  4 /**
  5  *  This exception is uncatchable !
  6  */
  7 void
  8 do_throw_uncatchable
  9     ( void )
 10 {
 11     // Simulate a boost::asio::error
 12     boost::asio::detail::throw_error( boost::asio::error::eof, "asio" );
 13 }
 14
 15 /**
 16  *  Now the exceptions thrown becomes catchable,
 17  *  when the function lives in an anonymous namespace.
 18  */
 19 namespace {
 20
 21 void
 22 do_throw_catchable
 23     ( void )
 24 {
 25     // Simulate a boost::asio::error
 26     boost::asio::detail::throw_error( boost::asio::error::eof, "asio" );
 27 }
 28
 29 } // anonymous namespace
 30
 31
 32 /**
 33  *  Expect:
 34  *  #############
 35  *  catched catchable
 36  *  catched uncatchable
 37  *  ############
 38  *
 39  *  But see:
 40  *  #############
 41  *  cacthed catchable
 42  *  terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::system::system_error> >'
 43  *    what():  asio: End of file
 44  *    Abort trap (core dumped)
 45  *  #############
 46  */
 47 int
 48 main
 49     ( int argc
 50     , char* argv[] )
 51 {
 52     try
 53     {
 54         do_throw_catchable();
 55     }
 56     catch ( std::exception const& )
 57     {
 58         std::cout << "catched catchable" << std::endl;
 59     }
 60
 61     try
 62     {
 63         do_throw_uncatchable();
 64     }
 65     catch ( std::exception const& )
 66     {
 67         std::cout << "catched uncatchable" << std::endl;
 68     }
 69
 70     return 0;
 71 }
 72


g++48  -ftemplate-depth-128 --std=c++11 -Os -finline-functions -Wno-inline -Wall -pthread  -DBOOST_ALL_NO_LIB -DBOOST_ASIO_HAS_MOVE -DNDEBUG -c -o "bin/gcc-4.8/release/link-static/optimization-space/threading-multi/main.o" "main.cpp"

g++48    -o "bin/gcc-4.8/release/link-static/optimization-space/threading-multi/main" -Wl,--start-group "bin/gcc-4.8/release/link-static/optimization-space/threading-multi/main.o"  -Wl,-Bstatic -lboost_system -Wl,-Bdynamic  -Wl,--end-group -Wl,-rpath,/usr/local/lib/gcc48 -Wl,--strip-all -pthread



I'll try to reproduce without boost.
Comment 1 David Keller 2012-08-15 02:09:47 UTC
Err:
Pasted command line show use of -Os which does *NOT* reproduce the behavior.
Please use -O3.
Comment 2 David Keller 2012-08-15 02:58:33 UTC
  1 #include <iostream>
  2 #include <boost/system/error_code.hpp>
  3 #include <boost/system/system_error.hpp>
  4
  5
  6 namespace detail {
  7
  8 inline void throw_error(const boost::system::error_code& err)
  9 {
 10     /**
 11      * If this condition is removed, (i.e. always throw)
 12      * Then the exception will be caught!!
 13      */
 14     if ( err )
 15     {
 16         boost::system::system_error e(err);
 17         throw e;
 18     }
 19 }
 20
 21 } // namespace detail
 22
 23 /**
 24  *  This exception is not catchable !
 25  */
 26 void
 27 do_throw_bad
 28     ( void )
 29 {
 30     // Simulate a boost::asio::error
 31     detail::throw_error( boost::system::errc::make_error_code( boost::system::errc::address_in_use ));
 32 }
 33
 34 /**
 35  *  Now the exceptions thrown becomes catchable.
 36  *  When the function lives in an anonymous namespace.
 37  */
 38 namespace {
 39
 40 void
 41 do_throw_ok
 42     ( void )
 43 {
 44     // Simulate a boost::asio::error
 45     detail::throw_error( boost::system::errc::make_error_code( boost::system::errc::address_in_use ));
 46 }
 47
 48 } // anonymous namespace
 49 [...]

When the if condition is removed from the throw_error function, the exception is caught!

I'll continue to simplify the case.
Comment 3 Andrew Pinski 2012-08-15 03:01:03 UTC
Can you remove the boost dependency?  Also does this work with the shared libgcc?
Comment 4 David Keller 2012-08-15 03:05:29 UTC
I'am trying. 
It's not reproducible with <system_error> classes.

Static build seems to use shared libgcc_s:
$ldd bin/gcc-4.7/release/link-static/threading-multi/main
bin/gcc-4.7/release/link-static/threading-multi/main:
        libstdc++.so.6 => /usr/local/lib/gcc47/libstdc++.so.6 (0x80084d000)
        libm.so.5 => /lib/libm.so.5 (0x800b55000)
        libgcc_s.so.1 => /usr/local/lib/gcc47/libgcc_s.so.1 (0x800d76000)
        libthr.so.3 => /lib/libthr.so.3 (0x800f8b000)
        libc.so.7 => /lib/libc.so.7 (0x8011ae000)

Shared build reproduces.
Comment 5 David Keller 2012-08-15 03:16:30 UTC
  1 #include <iostream>
  2 #include <stdexcept>
  3
  4 namespace detail {
  5
  6 inline void throw_error(bool t)
  7 {
  8     /**
  9      * If this condition is removed, (i.e. always throw)
 10      * Then the exception will be catched !!
 11      */
 12     if ( t )
 13     {
 14         std::runtime_error e("failed");
 15         throw e;
 16     }
 17 }
 18
 19 inline void this_function_is_required ( void )
 20 {
 21     std::cout << "do not remove on optimization" << std::endl;
 22 }
 23
 24 } // namespace detail
 25
 26 /**
 27  *  This exception is not catchable !
 28  */
 29 void
 30 do_throw_bad
 31     ( bool b )
 32 {
 33     // Simulate a boost::asio::error
 34     //boost::system::errc::make_error_code( boost::system::errc::address_in_use );
 35     detail::this_function_is_required();
 36     detail::throw_error( b );
 37 }
 38
 39 /**
 40  *  Expect:
 41  *  #############
 42  *  catched bad
 43  *  ############
 44  *
 45  *  But see:
 46  *  #############
 47  *  terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::system::system_error> >'
 48  *    what():  asio: End of file
 49  *    Abort trap (core dumped)
 50  *  #############
 51  */
 52 int
 53 main
 54     ( int argc
 55     , char* argv[] )
 56 {
 57     try
 58     {
 59         do_throw_bad( argc == 1 );
 60     }
 61     catch ( std::exception const& )
 62     {
 63         std::cout << "catched" << std::endl;
 64     }
 65
 66     return 0;
 67 }
 68
         
Et voilĂ 
Comment 6 David Keller 2012-08-15 03:34:07 UTC
Created attachment 28018 [details]
Here is the faulty code.

# Hum, without this variable, the program runs fine.
# Is it finding the wrong version of stdlib ?
setenv LD_LIBRARY_PATH /lib:/usr/local/bin:/usr/local/lib:/usr/local/lib32:/usr/local/lib64

g++47 -O3 -Wl,-rpath,/usr/local/lib/gcc47 main.cpp && ./a.out
Comment 7 David Keller 2012-08-15 03:39:56 UTC
It might be related to a wrong stdlib selection on my side:

1) Without setenv LD_LIBRARY_PATH /lib:/usr/local/bin:/usr/local/lib:/usr/local/lib32:/usr/local/lib64, the program runs fine.
2) It is linked with -rpath,/usr/local/lib/gcc48 (and rpath should have priority over LD_LIBRARy_PATH)

*) Why optimization level has an influence on all this ?
Comment 8 David Keller 2012-08-15 15:55:16 UTC
According to http://www.freebsd.org/cgi/query-pr.cgi?pr=28191, the man is wrong, FreeBSD look at LD_LIBRARY_PATH before rpath.

So, when LD_LIBRARY_PATH contains /lib:, it crashes as seen in this thread.
The test program picks the wrong lib libgcc_s !

Not a GCC bug then :-)
Do you agree ?

(I don't get why O3 makes program requiring the last libgcc_s, I'll expect it to be required regardless of optimization level)