Open cmazakas opened 7 months ago
Given the following code, I notice that if I read from the pipe using io_uring, I get a (seeming) false positive from tsan
Consider:
#include <thread> #include <cassert> #include <memory> #include <iostream> #include <chrono> #include <unistd.h> #include <liburing.h> int main() { io_uring ring; io_uring_queue_init(8, &ring, 0); int pipe_fds[2]={-1,-1}; int ret=-1; ret=pipe(pipe_fds); if(ret==-1){return errno;} int x=-1; std::jthread t([&x,fd=pipe_fds[1]]()mutable{ auto p=std::make_unique<int>(1337); std::this_thread::sleep_for(std::chrono::seconds(1)); auto buf=p.release(); *buf=7331; x=INT_MAX; write(fd,&buf,sizeof(buf)); }); int* q=nullptr; auto sqe=io_uring_get_sqe(&ring); io_uring_prep_read(sqe,pipe_fds[0],&q,sizeof(q),0); io_uring_submit(&ring); io_uring_cqe* cqe=nullptr; io_uring_wait_cqe(&ring,&cqe); io_uring_cqe_seen(&ring,cqe); //read(pipe_fds[0],&q,sizeof(q)); std::unique_ptr<int> p(q); std::cout<<*p<<std::endl; std::cout<<x<<std::endl; io_uring_queue_exit(&ring); }
produces:
exbigboss@exbigboss-ubuntu ~/cpp/tsan ❯ uname -a Linux exbigboss-ubuntu 6.5.0-17-generic #17-Ubuntu SMP PREEMPT_DYNAMIC Thu Jan 11 14:01:59 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux exbigboss@exbigboss-ubuntu ~/cpp/tsan ❯ clang++-17 -fsanitize=thread -std=c++20 a.cpp ~/cpp/__install__/lib/liburing.a -I ~/cpp/__install__/include/ && ./a.out ================== WARNING: ThreadSanitizer: data race (pid=164382) Read of size 4 at 0x7b0400000800 by main thread: #0 main <null> (a.out+0xea978) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) Previous write of size 8 at 0x7b0400000800 by thread T1: #0 operator new(unsigned long) <null> (a.out+0xe985b) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) #1 std::__detail::_MakeUniq<int>::__single_object std::make_unique<int, int>(int&&) <null> (a.out+0xee296) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) #2 main::$_0::operator()() a.cpp (a.out+0xebc48) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) #3 void std::__invoke_impl<void, main::$_0>(std::__invoke_other, main::$_0&&) a.cpp (a.out+0xebbd5) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) #4 std::__invoke_result<main::$_0>::type std::__invoke<main::$_0>(main::$_0&&) a.cpp (a.out+0xebb45) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) #5 void std::thread::_Invoker<std::tuple<main::$_0>>::_M_invoke<0ul>(std::_Index_tuple<0ul>) a.cpp (a.out+0xebafd) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) #6 std::thread::_Invoker<std::tuple<main::$_0>>::operator()() a.cpp (a.out+0xebaa5) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) #7 std::thread::_State_impl<std::thread::_Invoker<std::tuple<main::$_0>>>::_M_run() a.cpp (a.out+0xeb969) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) #8 execute_native_thread_routine /build/gcc-13-XYspKM/gcc-13-13.2.0/build/x86_64-linux-gnu/libstdc++-v3/src/c++11/../../../../../src/libstdc++-v3/src/c++11/thread.cc:104:18 (libstdc++.so.6+0xe6332) (BuildId: 102661775a59c09123f226bc3021556fd42bc563) Location is heap block of size 4 at 0x7b0400000800 allocated by thread T1: #0 operator new(unsigned long) <null> (a.out+0xe985b) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) #1 std::__detail::_MakeUniq<int>::__single_object std::make_unique<int, int>(int&&) <null> (a.out+0xee296) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) #2 main::$_0::operator()() a.cpp (a.out+0xebc48) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) #3 void std::__invoke_impl<void, main::$_0>(std::__invoke_other, main::$_0&&) a.cpp (a.out+0xebbd5) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) #4 std::__invoke_result<main::$_0>::type std::__invoke<main::$_0>(main::$_0&&) a.cpp (a.out+0xebb45) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) #5 void std::thread::_Invoker<std::tuple<main::$_0>>::_M_invoke<0ul>(std::_Index_tuple<0ul>) a.cpp (a.out+0xebafd) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) #6 std::thread::_Invoker<std::tuple<main::$_0>>::operator()() a.cpp (a.out+0xebaa5) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) #7 std::thread::_State_impl<std::thread::_Invoker<std::tuple<main::$_0>>>::_M_run() a.cpp (a.out+0xeb969) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) #8 execute_native_thread_routine /build/gcc-13-XYspKM/gcc-13-13.2.0/build/x86_64-linux-gnu/libstdc++-v3/src/c++11/../../../../../src/libstdc++-v3/src/c++11/thread.cc:104:18 (libstdc++.so.6+0xe6332) (BuildId: 102661775a59c09123f226bc3021556fd42bc563) Thread T1 (tid=164384, finished) created by main thread at: #0 pthread_create <null> (a.out+0x605ff) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) #1 __gthread_create /build/gcc-13-XYspKM/gcc-13-13.2.0/build/x86_64-linux-gnu/libstdc++-v3/include/x86_64-linux-gnu/bits/gthr-default.h:663:35 (libstdc++.so.6+0xe6408) (BuildId: 102661775a59c09123f226bc3021556fd42bc563) #2 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State>>, void (*)()) /build/gcc-13-XYspKM/gcc-13-13.2.0/build/x86_64-linux-gnu/libstdc++-v3/src/c++11/../../../../../src/libstdc++-v3/src/c++11/thread.cc:172:37 (libstdc++.so.6+0xe6408) #3 std::thread std::jthread::_S_create<main::$_0>(std::stop_source&, main::$_0&&) a.cpp (a.out+0xeb6a1) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) #4 std::jthread::jthread<main::$_0, void>(main::$_0&&) a.cpp (a.out+0xeab25) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) #5 main <null> (a.out+0xea862) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) SUMMARY: ThreadSanitizer: data race (/home/exbigboss/cpp/tsan/a.out+0xea978) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) in main ================== 7331 /usr/bin/llvm-symbolizer-17: error: '[stack]': No such file or directory ================== WARNING: ThreadSanitizer: data race (pid=164382) Read of size 4 at 0x7ffe8cd593d0 by main thread: #0 main <null> (a.out+0xea9bd) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) Previous write of size 4 at 0x7ffe8cd593d0 by thread T1: #0 main::$_0::operator()() a.cpp (a.out+0xebcdc) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) #1 void std::__invoke_impl<void, main::$_0>(std::__invoke_other, main::$_0&&) a.cpp (a.out+0xebbd5) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) #2 std::__invoke_result<main::$_0>::type std::__invoke<main::$_0>(main::$_0&&) a.cpp (a.out+0xebb45) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) #3 void std::thread::_Invoker<std::tuple<main::$_0>>::_M_invoke<0ul>(std::_Index_tuple<0ul>) a.cpp (a.out+0xebafd) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) #4 std::thread::_Invoker<std::tuple<main::$_0>>::operator()() a.cpp (a.out+0xebaa5) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) #5 std::thread::_State_impl<std::thread::_Invoker<std::tuple<main::$_0>>>::_M_run() a.cpp (a.out+0xeb969) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) #6 execute_native_thread_routine /build/gcc-13-XYspKM/gcc-13-13.2.0/build/x86_64-linux-gnu/libstdc++-v3/src/c++11/../../../../../src/libstdc++-v3/src/c++11/thread.cc:104:18 (libstdc++.so.6+0xe6332) (BuildId: 102661775a59c09123f226bc3021556fd42bc563) Location is stack of main thread. Location is global '??' at 0x7ffe8cd3a000 ([stack]+0x1f3d0) Thread T1 (tid=164384, finished) created by main thread at: #0 pthread_create <null> (a.out+0x605ff) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) #1 __gthread_create /build/gcc-13-XYspKM/gcc-13-13.2.0/build/x86_64-linux-gnu/libstdc++-v3/include/x86_64-linux-gnu/bits/gthr-default.h:663:35 (libstdc++.so.6+0xe6408) (BuildId: 102661775a59c09123f226bc3021556fd42bc563) #2 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State>>, void (*)()) /build/gcc-13-XYspKM/gcc-13-13.2.0/build/x86_64-linux-gnu/libstdc++-v3/src/c++11/../../../../../src/libstdc++-v3/src/c++11/thread.cc:172:37 (libstdc++.so.6+0xe6408) #3 std::thread std::jthread::_S_create<main::$_0>(std::stop_source&, main::$_0&&) a.cpp (a.out+0xeb6a1) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) #4 std::jthread::jthread<main::$_0, void>(main::$_0&&) a.cpp (a.out+0xeab25) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) #5 main <null> (a.out+0xea862) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) SUMMARY: ThreadSanitizer: data race (/home/exbigboss/cpp/tsan/a.out+0xea9bd) (BuildId: c37a21adbd15c7d0b664b44dd7a19b1d98583db9) in main ================== 2147483647 ThreadSanitizer: reported 2 warnings
However, commenting out the pipe read from io_uring and instead using the blocking read() call directly does not produce these warnings.
read()
Given the following code, I notice that if I read from the pipe using io_uring, I get a (seeming) false positive from tsan
Consider:
produces:
However, commenting out the pipe read from io_uring and instead using the blocking
read()
call directly does not produce these warnings.