Bug 54297

Summary: [C++11] Segmentation fault with std::async and released shared state
Product: gcc Reporter: Ai Azuma <ai.azuma>
Component: libstdc++Assignee: Jonathan Wakely <redi>
Status: RESOLVED FIXED    
Severity: normal    
Priority: P3    
Version: 4.8.0   
Target Milestone: 4.7.2   
Host: Target:
Build: Known to work: 4.6.4
Known to fail: 4.7.2, 4.8.0 Last reconfirmed: 2012-08-17 00:00:00
Attachments: Command-line log

Description Ai Azuma 2012-08-17 15:13:59 UTC
Created attachment 28043 [details]
Command-line log

The following code causes segfault with GCC 4.8.0 20120812, -std=c++11 and -pthread.

/////////////////////////////////////////////////////////////
#include <chrono>
#include <thread>
#include <future>

int work()
{
  std::this_thread::sleep_for(std::chrono::seconds(1));
  return 0;
}

int main()
{
  // Note that the following explicitly named future object
  // is not necessary to reproduce the problem.
  std::future<int> f = std::async(std::launch::async, &work);
}
/////////////////////////////////////////////////////////////

The last invocation of std::future<int>'s destructor blocks the calling thread until the thread launched by std::async finishes the work, according to the 4th bullet of [futures.async]/5. Therefore, this program should terminate successfully.

This program also results in segfault with GCC 4.7.2 20120811, but not with 4.6.4 20120810.
Comment 1 Jonathan Wakely 2012-08-17 15:32:29 UTC
I suspect the problem is that when _Async_state_common calls _M_thread.join() to wait for the async task, the derived destructor of _Async_state_impl has already run and has destroyed the shared state.

If that's correct, the fix would be to add:

      ~_Async_state_impl() { _M_join(); }
Comment 2 Jonathan Wakely 2012-08-25 23:01:44 UTC
Author: redi
Date: Sat Aug 25 23:01:40 2012
New Revision: 190672

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=190672
Log:
	PR libstdc++/54297
	* include/std/future (~_Async_state_impl): Join thread before
	derived class members are destroyed.
	(~_Async_state_common): Only define non-trivial destructor when
	included from future.cc for ABI compatibility reasons.
	* src/c++11/future.cc (_GLIBCXX_ABI_COMPAT_ASYNC): Define.
	* testsuite/30_threads/async/54297.cc: New.

Added:
    trunk/libstdc++-v3/testsuite/30_threads/async/54297.cc
Modified:
    trunk/libstdc++-v3/ChangeLog
    trunk/libstdc++-v3/include/std/future
    trunk/libstdc++-v3/src/c++11/future.cc
Comment 3 Jonathan Wakely 2012-08-25 23:06:11 UTC
Author: redi
Date: Sat Aug 25 23:06:07 2012
New Revision: 190673

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=190673
Log:
	PR libstdc++/54297
	* include/std/future (~_Async_state_impl): Join thread before
	derived class members are destroyed.
	(~_Async_state_common): Only define non-trivial destructor when
	included from future.cc for ABI compatibility reasons.
	* src/c++11/future.cc (_GLIBCXX_ABI_COMPAT_ASYNC): Define.
	* testsuite/30_threads/async/54297.cc: New.

Added:
    branches/gcc-4_7-branch/libstdc++-v3/testsuite/30_threads/async/54297.cc
Modified:
    branches/gcc-4_7-branch/libstdc++-v3/ChangeLog
    branches/gcc-4_7-branch/libstdc++-v3/include/std/future
    branches/gcc-4_7-branch/libstdc++-v3/src/c++11/future.cc
Comment 4 Jonathan Wakely 2012-08-25 23:06:50 UTC
fixed
Comment 5 Jonathan Wakely 2012-08-26 13:49:51 UTC
Author: redi
Date: Sun Aug 26 13:49:44 2012
New Revision: 190685

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=190685
Log:
	PR libstdc++/54297
	* src/c++11/future.cc (~_Async_state_common): Move to...
	* src/c++11/compatibility-thread-c++0x.cc (~_Async_state_common):
	Here.
	(_GLIBCXX_ABI_COMPAT_ASYNC): Rename to _GLIBCXX_ASYNC_ABI_COMPAT.
	* include/std/future (_GLIBCXX_ABI_COMPAT_ASYNC): Likewise.

Modified:
    trunk/libstdc++-v3/ChangeLog
    trunk/libstdc++-v3/include/std/future
    trunk/libstdc++-v3/src/c++11/compatibility-thread-c++0x.cc
    trunk/libstdc++-v3/src/c++11/future.cc
Comment 6 Jonathan Wakely 2012-08-26 14:09:20 UTC
Author: redi
Date: Sun Aug 26 14:09:12 2012
New Revision: 190687

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=190687
Log:
	PR libstdc++/54297
	* src/c++11/future.cc (~_Async_state_common): Move to...
	* src/c++11/compatibility-thread-c++0x.cc (~_Async_state_common):
	Here.
	(_GLIBCXX_ABI_COMPAT_ASYNC): Rename to _GLIBCXX_ASYNC_ABI_COMPAT.
	* include/std/future (_GLIBCXX_ABI_COMPAT_ASYNC): Likewise.

Modified:
    branches/gcc-4_7-branch/libstdc++-v3/ChangeLog
    branches/gcc-4_7-branch/libstdc++-v3/include/std/future
    branches/gcc-4_7-branch/libstdc++-v3/src/c++11/compatibility-thread-c++0x.cc
    branches/gcc-4_7-branch/libstdc++-v3/src/c++11/future.cc