[Bug libstdc++/55917] Impossible to find/debug unhandled exceptions in an std::thread

2017-06-12 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55917

Jonathan Wakely  changed:

   What|Removed |Added

 Status|UNCONFIRMED |RESOLVED
 Resolution|--- |FIXED
   Target Milestone|--- |8.0

--- Comment #17 from Jonathan Wakely  ---
Fixed for GCC 8.

[Bug libstdc++/55917] Impossible to find/debug unhandled exceptions in an std::thread

2017-06-12 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55917

--- Comment #16 from Jonathan Wakely  ---
Author: redi
Date: Mon Jun 12 16:37:28 2017
New Revision: 249130

URL: https://gcc.gnu.org/viewcvs?rev=249130=gcc=rev
Log:
PR libstdc++/55917 do not handle exceptions in std::thread

PR libstdc++/55917
* src/c++11/thread.cc (execute_native_thread_routine): Remove
try-block so that exceptions propagate out of the thread and terminate
is called by the exception-handling runtime.
(execute_native_thread_routine_compat): Likewise.
* testsuite/30_threads/thread/cons/terminate.cc: New.

Added:
trunk/libstdc++-v3/testsuite/30_threads/thread/cons/terminate.cc
Modified:
trunk/libstdc++-v3/ChangeLog
trunk/libstdc++-v3/src/c++11/thread.cc

[Bug libstdc++/55917] Impossible to find/debug unhandled exceptions in an std::thread

2016-06-20 Thread howard.hinnant at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55917

--- Comment #15 from Howard Hinnant  ---
To help clarify my proposal, here is a patch:

diff --git a/libstdc++-v3/src/c++11/thread.cc
b/libstdc++-v3/src/c++11/thread.cc
index 906cafa..cfca178 100644
--- a/libstdc++-v3/src/c++11/thread.cc
+++ b/libstdc++-v3/src/c++11/thread.cc
@@ -79,19 +79,7 @@ namespace std _GLIBCXX_VISIBILITY(default)
   thread::__shared_base_type __local;
   __local.swap(__t->_M_this_ptr);

-  __try
-   {
- __t->_M_run();
-   }
-  __catch(const __cxxabiv1::__forced_unwind&)
-   {
- __throw_exception_again;
-   }
-  __catch(...)
-   {
- std::terminate();
-   }
-
+   __t->_M_run();
   return nullptr;
 }
   }

My colleague Miguel Portilla has tested this patch with the following code:

#include 
#include 

void a(int i);
void b(int i);
void c(int i);

int
main()
{
auto t = std::thread{a, 3};
t.join();
}

void
a(int i)
{
b(i-1);
}

void
b(int i)
{
c(i-1);
}

void
c(int i)
{
throw std::runtime_error("A good message");
}

And the stack dump looks like:

Thread 2 (Thread 0x7f090b47c740 (LWP 1865)):
#0  0x7f090b0688ed in pthread_join (threadid=139676803389184,
thread_return=0x0) at pthread_join.c:90
#1  0x7f090ad9c767 in __gthread_join (__value_ptr=0x0,
__threadid=)
at
/home/mickey/gcc-5.4.0/build/x86_64-linux-gnu/libstdc++-v3/include/x86_64-linux-gnu/bits/gthr-default.h:668
#2  std::thread::join (this=0x7ffd1dae6430) at
../../../../../libstdc++-v3/src/c++11/thread.cc:96
#3  0x00400f39 in main ()

Thread 1 (Thread 0x7f090a3fd700 (LWP 1866)):
#0  0x7f090a433267 in __GI_raise (sig=sig@entry=6) at
../sysdeps/unix/sysv/linux/raise.c:55
#1  0x7f090a434eca in __GI_abort () at abort.c:89
#2  0x7f090ad747dd in __gnu_cxx::__verbose_terminate_handler ()
at ../../../../libstdc++-v3/libsupc++/vterminate.cc:95
#3  0x7f090ad72866 in __cxxabiv1::__terminate (handler=)
at ../../../../libstdc++-v3/libsupc++/eh_terminate.cc:47
#4  0x7f090ad728b1 in std::terminate () at
../../../../libstdc++-v3/libsupc++/eh_terminate.cc:57
#5  0x7f090ad72ac8 in __cxxabiv1::__cxa_throw (obj=0x7f0904000940, 
tinfo=0x604360 , 
dest=0x400ce0 ) at
../../../../libstdc++-v3/libsupc++/eh_throw.cc:87
#6  0x00400fdd in c(int) ()
#7  0x00400fa0 in b(int) ()
#8  0x00400f85 in a(int) ()
#9  0x00402574 in void std::_Bind_simple::_M_invoke<0ul>(std::_Index_tuple<0ul>) ()
#10 0x00402493 in std::_Bind_simple::operator()()
()
#11 0x00402432 in std::thread::_Impl::_M_run() ()
#12 0x7f090ad9c820 in std::execute_native_thread_routine (__p=)
at ../../../../../libstdc++-v3/src/c++11/thread.cc:82
#13 0x7f090b0676aa in start_thread (arg=0x7f090a3fd700) at
pthread_create.c:333
#14 0x7f090a504e9d in clone () at
../sysdeps/unix/sysv/linux/x86_64/clone.S:109

[Bug libstdc++/55917] Impossible to find/debug unhandled exceptions in an std::thread

2016-05-20 Thread howard.hinnant at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55917

Howard Hinnant  changed:

   What|Removed |Added

 CC||howard.hinnant at gmail dot com

--- Comment #14 from Howard Hinnant  ---
The main function is not wrapped in a try / catch and an unhandled exception on
the main thread still calls std::terminate() as required.

I believe that gcc already correctly implements the call to std::terminate()
for threads elsewhere, and with the same code that it does for main.  It is in
the function __cxa_throw, implemented by libsupc++.  Here is the specification:

http://mentorembedded.github.io/cxx-abi/abi-eh.html#cxx-throw

which says in part:

> __Unwind_RaiseException begins the process of stack unwinding, described in 
> Section 2.5. In special cases, such as an inability to find a handler, 
> _Unwind_RaiseException may return. In that case, __cxa_throw will call 
> terminate, assuming that there was no handler for the exception.

And here is where it is implemented:

https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/eh_throw.cc#L87

As long as libsupc++ is being used on the platform, I think you are good to
remove the try/catch from execute_native_thread_routine.

Fwiw, this is what is done on libc++ / libc++abi (no try/catch at the top of
std::thread, and let __cxa_throw call terminate).  We get beautiful stack dumps
from threaded code over there. :-)

[Bug libstdc++/55917] Impossible to find/debug unhandled exceptions in an std::thread

2014-11-24 Thread rogero at howzatt dot demon.co.uk
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55917

Roger Orr rogero at howzatt dot demon.co.uk changed:

   What|Removed |Added

 CC||rogero at howzatt dot 
demon.co.uk

--- Comment #13 from Roger Orr rogero at howzatt dot demon.co.uk ---
I am also affected by this problem.
What is the status of the idea Jonathan made (2013-07-02 11:26:53 UTC):

  ... and I think we can make a change for targets where we know the behaviour
is OK ...


[Bug libstdc++/55917] Impossible to find/debug unhandled exceptions in an std::thread

2013-07-02 Thread yuri.aksenov at gmail dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55917

Yuri Aksenov yuri.aksenov at gmail dot com changed:

   What|Removed |Added

 CC||yuri.aksenov at gmail dot com

--- Comment #7 from Yuri Aksenov yuri.aksenov at gmail dot com ---
 If it's guaranteed that an uncaught exception leaving that function will 
 still 
 call terminate, then the catch(...) block could be removed. Maybe I could do 
 that conditionally for targets where it's known to work as required.

I vote for this enhancement to remove catch(...) block from
execute_native_thread_routine function.

According to standard (15.3) Handling an exception
 If no matching handler is found, the function std::terminate() is called; 
 whether or not the stack is unwound before this call to std::terminate() is 
 implementation-defined (15.5.1).

So if we remove catch(...), std::terminate should be called anyway (it's a bug
otherwise). But GCC implementaion will leave stack unwound making it easier to
debug.

[Bug libstdc++/55917] Impossible to find/debug unhandled exceptions in an std::thread

2013-07-02 Thread redi at gcc dot gnu.org
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55917

--- Comment #8 from Jonathan Wakely redi at gcc dot gnu.org ---
(In reply to Yuri Aksenov from comment #7)
  If it's guaranteed that an uncaught exception leaving that function will 
  still 
  call terminate, then the catch(...) block could be removed. Maybe I could 
  do 
  that conditionally for targets where it's known to work as required.
 
 I vote for this enhancement to remove catch(...) block from
 execute_native_thread_routine function.

This isn't a democracy ;)

 According to standard (15.3) Handling an exception
  If no matching handler is found, the function std::terminate() is called; 
  whether or not the stack is unwound before this call to std::terminate() is 
  implementation-defined (15.5.1).
 
 So if we remove catch(...), std::terminate should be called anyway (it's a
 bug otherwise).

The catch(...) is there to provide the [thread.thread.constr]/4 requirement
that std::terminate is called. If it isn't there, are you saying Pthreads or
the OS guarantees that an exception in the function passed to pthread_create()
will cause a call to std::terminate()? Where is that guaranteed?  Where is it
implemented?

You can't just say rely on the implementation, it's a bug otherwise, this
code **is** the implementation.

[Bug libstdc++/55917] Impossible to find/debug unhandled exceptions in an std::thread

2013-07-02 Thread redi at gcc dot gnu.org
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55917

--- Comment #9 from Jonathan Wakely redi at gcc dot gnu.org ---
P.S. I do want to improve the behaviour, and I think we can make a change for
targets where we know the behaviour is OK, but we need to check carefully that
it works correctly, not just remove the catch(...)


[Bug libstdc++/55917] Impossible to find/debug unhandled exceptions in an std::thread

2013-07-02 Thread yuri.aksenov at gmail dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55917

--- Comment #10 from Yuri Aksenov yuri.aksenov at gmail dot com ---
OK, [thread.thread.constr]/4 says:
 If the invocation of INVOKE(decay_copy( std::forwardF(f)), 
 decay_copy(std::forwardArgs(args))...) terminates with an uncaught 
 exception, 
 std::terminate shall be called.

And [except.handle]/9 says:
 If no matching handler is found, the function std::terminate() is called

So we don't need to set default handler unless there is bug in implementation
of [except.handle]/9

I have tested std::thread with removed catch(...) for both -m32 and -m64
environments on
gcc version 4.7.1 20120723 [gcc-4_7-branch revision 189773] (SUSE Linux) 
Target: x86_64-suse-linux

And I can test it on
Target: armv5b-softfloat-linux

But I can not be shure for any possible target


[Bug libstdc++/55917] Impossible to find/debug unhandled exceptions in an std::thread

2013-07-02 Thread yuri.aksenov at gmail dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55917

--- Comment #11 from Yuri Aksenov yuri.aksenov at gmail dot com ---
 Where is that guaranteed?  Where is it implemented?

And here is stack trace of patched version, it seems to be implemented in
__cxxabiv1::__cxa_throw

(gdb) bt
#0  0x7703ad25 in __GI_raise (sig=sig@entry=6) at
../nptl/sysdeps/unix/sysv/linux/raise.c:64
#1  0x7703c1a8 in __GI_abort () at abort.c:91
#2  0x7791d68d in __gnu_cxx::__verbose_terminate_handler () at
../../../../libstdc++-v3/libsupc++/vterminate.cc:95
#3  0x7791b796 in __cxxabiv1::__terminate (handler=optimized out) at
../../../../libstdc++-v3/libsupc++/eh_terminate.cc:40
#4  0x7791b7c3 in std::terminate () at
../../../../libstdc++-v3/libsupc++/eh_terminate.cc:50
#5  0x7791b9ee in __cxxabiv1::__cxa_throw (obj=0x7940,
tinfo=optimized out, dest=optimized out) at
../../../../libstdc++-v3/libsupc++/eh_throw.cc:83
#6  0x004010f2 in f () at main.cpp:5
#7  0x0040242d in std::_Bind_simplevoid
(*())()::_M_invoke(std::_Index_tuple) (this=0x606040) at
/usr/include/c++/4.7/functional:1598
#8  0x0040237d in std::_Bind_simplevoid (*())()::operator()()
(this=0x606040) at /usr/include/c++/4.7/functional:1586
#9  0x00402316 in std::thread::_Implstd::_Bind_simplevoid (*())()
::_M_run() (this=0x606028) at /usr/include/c++/4.7/thread:115
#10 0x0040266d in std::(anonymous
namespace)::execute_native_thread_routine (__p=0x606028) at thread.cpp:73
#11 0x77bc6e0e in start_thread (arg=0x77005700) at
pthread_create.c:305
#12 0x770ea2cd in clone () at
../sysdeps/unix/sysv/linux/x86_64/clone.S:115


[Bug libstdc++/55917] Impossible to find/debug unhandled exceptions in an std::thread

2013-07-02 Thread redi at gcc dot gnu.org
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55917

--- Comment #12 from Jonathan Wakely redi at gcc dot gnu.org ---
Yes it will probably work on all platforms using the Itanium exception-handling
ABI, unless the OS's pthread_create (or equiv) has explicit exception-handling.


[Bug libstdc++/55917] Impossible to find/debug unhandled exceptions in an std::thread

2013-01-09 Thread tobias at ringis dot se

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55917

--- Comment #1 from Tobias Ringström tobias at ringis dot se 2013-01-09 
13:22:52 UTC ---
Created attachment 29120
  -- http://gcc.gnu.org/bugzilla/attachment.cgi?id=29120
Test program to illustrate the problem


[Bug libstdc++/55917] Impossible to find/debug unhandled exceptions in an std::thread

2013-01-09 Thread redi at gcc dot gnu.org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55917



Jonathan Wakely redi at gcc dot gnu.org changed:



   What|Removed |Added



   Severity|normal  |enhancement



--- Comment #2 from Jonathan Wakely redi at gcc dot gnu.org 2013-01-09 
13:44:35 UTC ---

As I said at http://gcc.gnu.org/ml/gcc-help/2013-01/msg00068.html this can't be

changed for std::thread, see

http://gcc.gnu.org/ml/libstdc++/2012-12/msg00062.html and the patch at

http://gcc.gnu.org/ml/libstdc++/2012-12/msg00068.html for discussion and code

that absolutely requires exceptions of type __forced_unwind to be able to

escape the thread start function, otherwise thread cancellation crashes the

program, which is not acceptable.



If the function is not noexcept then it must catch exceptions to ensure

std::terminate is called as required, and catching the exception causes the

stack to be unwound. So it's difficult do anything about std::thread.



Please open a separate bug (with Component=c++) for the

http://gcc.gnu.org/ml/gcc-help/2013-01/msg00058.html issue when noexcept

interacts with a destructor on the stack.  That applies to code not using

std::thread too.


[Bug libstdc++/55917] Impossible to find/debug unhandled exceptions in an std::thread

2013-01-09 Thread redi at gcc dot gnu.org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55917



--- Comment #3 from Jonathan Wakely redi at gcc dot gnu.org 2013-01-09 
13:48:04 UTC ---

Ah, I se PR 55918 - thanks!


[Bug libstdc++/55917] Impossible to find/debug unhandled exceptions in an std::thread

2013-01-09 Thread redi at gcc dot gnu.org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55917



--- Comment #4 from Jonathan Wakely redi at gcc dot gnu.org 2013-01-09 
13:59:58 UTC ---

One option would be to make the start function have a

dynamic-exception-specification of throw(__cxxabiv1::__forced_unwind), which

would allow the cancellation exception to propagate (as required) but prevent

any other exceptions, but that would result in a call to std::unexpected()

rather than std::terminate(), and a user could have replaced the

unexpected_handler, so we would not be able to meet the requirement that

std::terminate() is called. On top of that, I think the stack would still get

unwound before the call to std:unexpected, and dynamic-exception-specifications

and unexpected handlers are deprecated in C++11.  So I don't think we want to

do that.



My inclination is to close this as WONTFIX.


[Bug libstdc++/55917] Impossible to find/debug unhandled exceptions in an std::thread

2013-01-09 Thread tobias at ringis dot se

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55917

--- Comment #5 from Tobias Ringström tobias at ringis dot se 2013-01-09 
14:06:08 UTC ---
Yes, I thought two reports were in order, as they are only vaguely related.  To
me, this one is the most important problem.  I struggle to understand how I can
be the first to have this problem.  Surely it must be an enormous problem if
you use std::thread?  I'm working on a somewhat large multi-threaded program,
and if there's an exception anywhere, e.g. a failed range-check in a container,
it's *completely impossible* to find the problem in a debugger.  We've now
switched to boost::thread instead because it does not have this problem.

I must say that I'm very surprised that you call it an enhancement, and that
you consider closing it as WONTFIX, seeing how the current behavior is so
mindbogglingly unfriendly.  There is a reason why GCC does not unwind the stack
for non-threaded unhandled exceptions.

Perhaps std::thread is not widely used yet, or I'm the only one with buggy
code?


[Bug libstdc++/55917] Impossible to find/debug unhandled exceptions in an std::thread

2013-01-09 Thread redi at gcc dot gnu.org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55917



--- Comment #6 from Jonathan Wakely redi at gcc dot gnu.org 2013-01-09 
14:42:00 UTC ---

(In reply to comment #5)

 Yes, I thought two reports were in order, as they are only vaguely related.  
 To

 me, this one is the most important problem.  I struggle to understand how I 
 can

 be the first to have this problem.  Surely it must be an enormous problem if

 you use std::thread?  I'm working on a somewhat large multi-threaded program,

 and if there's an exception anywhere, e.g. a failed range-check in a 
 container,

 it's *completely impossible* to find the problem in a debugger.



If you're running in the debugger, rather than examining a core file

post-mortem, you can use catch throw or break __cxa_throw to break when the

exception is thrown.



Otherwise you already know the workaround, put 'noexcept' on the function you

pass to std::thread (which breaks pthread_cancel but if you're not using that

it doesn't matter.)



  We've now

 switched to boost::thread instead because it does not have this problem.

 

 I must say that I'm very surprised that you call it an enhancement,



The current implementation conforms to the standard.



 and that

 you consider closing it as WONTFIX,



I've explained why it can't easily be changed, unless anyone has some idea I

haven't thought of yet to preserve pthread_cancel behaviour and preserve the

requirement that std::terminate() is called.



 seeing how the current behavior is so

 mindbogglingly unfriendly.  There is a reason why GCC does not unwind the 
 stack

 for non-threaded unhandled exceptions.



The behaviour comes directly from the explicit requirement in the standard that

an unhandled exception in a std::thread must call std::terminate. 



If it's guaranteed that an uncaught exception leaving that function will still

call terminate, then the catch(...) block could be removed. Maybe I could do

that conditionally for targets where it's known to work as required.