https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113244
Bug ID: 113244
Summary: Potential thread sanitizer false positive with future
exception
Product: gcc
Version: 13.2.1
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: sanitizer
Assignee: unassigned at gcc dot gnu.org
Reporter: gcc-bugzilla at mhxnet dot de
CC: dodji at gcc dot gnu.org, dvyukov at gcc dot gnu.org,
jakub at gcc dot gnu.org, kcc at gcc dot gnu.org, marxin at
gcc dot gnu.org
Target Milestone: ---
Created attachment 56994
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=56994&action=edit
C++ code to reproduce the issue
Using `g++-13 (Gentoo 13.2.1_p20230826 p7) 13.2.1 20230826` and compiling the
attached program with
g++-13 -std=c++20 -g -O2 -fsanitize=thread -fno-omit-frame-pointer -o
packaged_task packaged_task.cpp
Thread Sanitizer will likely, but not always, report several data races related
to the exception stored in the future. The races are between reading from the
exception object in the catch block on the main thread and destroying the
exception as a result of packaged_task going out of scope in one of the worker
threads.
==
WARNING: ThreadSanitizer: data race on vptr (ctor/dtor vs virtual call)
(pid=7610)
Write of size 8 at 0x7b2c00031460 by thread T9:
#0 ~error_base /home/mhx/src/c++/test/packaged_task.cpp:12
(packaged_task+0x5574)
#1 ~my_error /home/mhx/src/c++/test/packaged_task.cpp:22
(packaged_task+0x5574)
#2 std::__exception_ptr::exception_ptr::_M_release()
/var/tmp/portage/sys-devel/gcc-13.2.1_p20230826/work/gcc-13-20230826/libstdc++-v3/libsupc++/eh_ptr.cc:105
(libstdc++.so.6+0xb2f30)
#3 std::__future_base::_Result::_M_destroy()
/usr/lib/gcc/x86_64-pc-linux-gnu/13/include/g++-v13/future:672
(packaged_task+0x5287)
#4
std::__future_base::_Result_base::_Deleter::operator()(std::__future_base::_Result_base*)
const /usr/lib/gcc/x86_64-pc-linux-gnu/13/include/g++-v13/future:229
(packaged_task+0x5287)
#5 std::unique_ptr::~unique_ptr()
/usr/lib/gcc/x86_64-pc-linux-gnu/13/include/g++-v13/bits/unique_ptr.h:404
(packaged_task+0x5287)
#6 std::__future_base::_State_baseV2::~_State_baseV2()
/usr/lib/gcc/x86_64-pc-linux-gnu/13/include/g++-v13/future:344
(packaged_task+0x5287)
#7 std::__future_base::_Task_state_base::~_Task_state_base()
/usr/lib/gcc/x86_64-pc-linux-gnu/13/include/g++-v13/future:1450
(packaged_task+0x5287)
#8 ~_Task_state
/usr/lib/gcc/x86_64-pc-linux-gnu/13/include/g++-v13/future:1477
(packaged_task+0x5287)
#9 destroy_at,
std::allocator, void()> >
/usr/lib/gcc/x86_64-pc-linux-gnu/13/include/g++-v13/bits/stl_construct.h:88
(packaged_task+0x5287)
#10 destroy,
std::allocator, void()> >
/usr/lib/gcc/x86_64-pc-linux-gnu/13/include/g++-v13/bits/alloc_traits.h:559
(packaged_task+0x5287)
#11 _M_dispose
/usr/lib/gcc/x86_64-pc-linux-gnu/13/include/g++-v13/bits/shared_ptr_base.h:613
(packaged_task+0x5287)
#12
std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release_last_use()
/usr/lib/gcc/x86_64-pc-linux-gnu/13/include/g++-v13/bits/shared_ptr_base.h:175
(packaged_task+0x83bc)
#13 std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release()
/usr/lib/gcc/x86_64-pc-linux-gnu/13/include/g++-v13/bits/shared_ptr_base.h:361
(packaged_task+0x83bc)
#14 std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count()
/usr/lib/gcc/x86_64-pc-linux-gnu/13/include/g++-v13/bits/shared_ptr_base.h:1071
(packaged_task+0x83bc)
#15 std::__shared_ptr,
(__gnu_cxx::_Lock_policy)2>::~__shared_ptr()
/usr/lib/gcc/x86_64-pc-linux-gnu/13/include/g++-v13/bits/shared_ptr_base.h:1524
(packaged_task+0x83bc)
#16 std::shared_ptr
>::~shared_ptr()
/usr/lib/gcc/x86_64-pc-linux-gnu/13/include/g++-v13/bits/shared_ptr.h:175
(packaged_task+0x83bc)
#17 std::packaged_task::~packaged_task()
/usr/lib/gcc/x86_64-pc-linux-gnu/13/include/g++-v13/future:1594
(packaged_task+0x83bc)
#18 std::_Optional_payload_base
>::_M_destroy()
/usr/lib/gcc/x86_64-pc-linux-gnu/13/include/g++-v13/optional:287
(packaged_task+0x645c)
#19 std::_Optional_payload_base
>::_M_reset() /usr/lib/gcc/x86_64-pc-linux-gnu/13/include/g++-v13/optional:318
(packaged_task+0x645c)
#20 std::_Optional_payload, false, false,
false>::~_Optional_payload()
/usr/lib/gcc/x86_64-pc-linux-gnu/13/include/g++-v13/optional:439
(packaged_task+0x645c)
#21 std::_Optional_base, false,
false>::~_Optional_base()
/usr/lib/gcc/x86_64-pc-linux-gnu/13/include/g++-v13/optional:510
(packaged_task+0x645c)
#22 std::optional >::~optional()
/usr/lib/gcc/x86_64-pc-linux-gnu/13/include/g++-v13/optional:705
(packaged_task+0x645c)
#23 worker /home/mhx/src/c++/test/packaged_task.cpp:45
(packaged_task+0x645c)
#24 void std::__invoke_i