[Bug sanitizer/113244] New: Potential thread sanitizer false positive with future exception

2024-01-05 Thread gcc-bugzilla at mhxnet dot de via Gcc-bugs
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

[Bug sanitizer/113244] Potential thread sanitizer false positive with future exception

2024-01-06 Thread gcc-bugzilla at mhxnet dot de via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113244

--- Comment #2 from Marcus Holland-Moritz  ---
(In reply to Andrew Pinski from comment #1)
> I suspect this is because libstdc++.so is NOT instrumented for TSAN.

This is certainly possible.

Is there documentation available on how to build a suitably instrumented
libstdc++.so?

I've spent a few hours now trying to build

- all of gcc-13.2/gcc-12.3
- only libstdc++-v3 from gcc-13.2/gcc-12.3

with the following flags:

  CFLAGS="-fsanitize=thread -g -O2 -fno-omit-frame-pointer"
  CXXFLAGS="-fsanitize=thread -g -O2 -fno-omit-frame-pointer"
  LDFLAGS="-fsanitize=thread"

All of my attempts failed due to strange errors (which I can list here more
systematically if desired). A "plain" gcc build with no sanitizer-specific
compiler/linker flags works just fine.

Given that "libstdc++.so is NOT instrumented for TSAN" is a frequent response
to similar false positive reports, I'm somewhat surprised by the lack of easily
discoverable information on how to build an instrumented library. It also makes
me wonder how useful the thread sanitizer (maybe other sanitizers as well) is
at all without such an instrumented library. If an instrumented library is a
requirement for `-fsanitize=thread` to work properly, there should probably
exist a `configure` option to automatically build the required instrumented
library versions (and ideally the right version would be used when linking with
`-fsanitize=thread`).