weak_ptr::lock crashes when the code is compiled with the -fno-exceptions flag and the data pointed by the weak_ptr expires during the execution of the lock function itself: (from http://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01518_source.html) shared_ptr<_Tp> 494 lock() const noexcept 495 { 496 #ifdef __GTHREADS 497 if (this->expired()) 498 return shared_ptr<_Tp>(); 499 500 __try 501 { 502 return shared_ptr<_Tp>(*this); 503 } 504 __catch(const bad_weak_ptr&) 505 { 506 return shared_ptr<_Tp>(); 507 } 508 #else 509 return this->expired() ? shared_ptr<_Tp>() : shared_ptr<_Tp>(*this); 510 #endif 511 } If the data is valid when line 497 is executed and the data is released in a different thread just before executing line 502, the program will crash because it will try to throw an exception (exceptions are disabled because of the flag -fno-exceptions). This code only works when exceptions are enabled because the try/catch will resolve the problem, but not otherwise. The standard definition says that this function must return safely and it doesn't throw any exception. I presume this must apply even if the exceptions are not enabled.
The standard says exceptions are always enabled, if you disable them you are no longer using standard C++, so what it says in the standard doesn't necessarily apply. I don't think it would be simple to make this work with -fno-exceptions
(In reply to Jonathan Wakely from comment #1) > The standard says exceptions are always enabled, if you disable them you are > no longer using standard C++, so what it says in the standard doesn't > necessarily apply. It's a quality of implementation issue: effectively current std::weak_ptr is not usable in any multithreaded program built with -fno-exceptions. > I don't think it would be simple to make this work with -fno-exceptions We have a patch that makes it work.
*** Bug 59869 has been marked as a duplicate of this bug. ***
Created attachment 31911 [details] test case Copy of test case from PR 59869
Thanks Paul. You mentioned a proposed patch, are you working on that? From a quick look I didn't see how to fix it without adding a _Sp_counted_base::_M_add_ref_lock_nothrow() function and adding new constructors taking an additional std::nothrow_t argument to the whole class hierarchy. Did you have a simpler fix in mind?
Created attachment 31920 [details] don't use _M_add_ref_lock() when exceptions are disabled Here's a patch which fixes Paul's testcase
Created attachment 31924 [details] Alternate fix from Kyle Lippincott Alternate patch, courtesy Kyle Lippincott <spectral@google.com>. AFAIU, Kyle's patch uses roughly the same idea as Jonathan's, but no #ifdef's. Should we take these patches to gcc-patches list?
Thanks, yes the general idea is identical. I prefer some parts of Kyle's fix but I don't want the new constructor to be public, so I'll combine the two patches and post it to gcc-patches next week.
Author: redi Date: Tue Jan 28 10:23:27 2014 New Revision: 207180 URL: http://gcc.gnu.org/viewcvs?rev=207180&root=gcc&view=rev Log: 2014-01-28 Jonathan Wakely <jwakely@redhat.com> Kyle Lippincott <spectral@google.com> PR libstdc++/59656 * include/bits/shared_ptr.h (shared_ptr): Add new non-throwing constructor and grant friendship to weak_ptr. (weak_ptr::lock()): Use new constructor. * include/bits/shared_ptr_base.h (_Sp_counted_base::_M_add_ref_lock_nothrow()): Declare new function and define specializations. (__shared_count): Add new non-throwing constructor. (__shared_ptr): Add new non-throwing constructor and grant friendship to __weak_ptr. (__weak_ptr::lock()): Use new constructor. * testsuite/20_util/shared_ptr/cons/43820_neg.cc: Adjust dg-error. * testsuite/20_util/shared_ptr/cons/void_neg.cc: Likewise. Modified: trunk/libstdc++-v3/ChangeLog trunk/libstdc++-v3/include/bits/shared_ptr.h trunk/libstdc++-v3/include/bits/shared_ptr_base.h trunk/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc trunk/libstdc++-v3/testsuite/20_util/shared_ptr/cons/void_neg.cc
Fixed on trunk
Author: ppluzhnikov Date: Tue Jan 28 19:08:00 2014 New Revision: 207201 URL: http://gcc.gnu.org/viewcvs?rev=207201&root=gcc&view=rev Log: For Google b/12533273 and PR 59656, partially backport r207180 from trunk. (The new test: libstdc++-v3/testsuite/20_util/shared_ptr/cons/void_neg.cc is not added, because it succeeds to compile with gcc-4_8.) Modified: branches/google/gcc-4_8/libstdc++-v3/include/bits/shared_ptr.h branches/google/gcc-4_8/libstdc++-v3/include/bits/shared_ptr_base.h branches/google/gcc-4_8/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc