曾与notify_all_at_thread_exit抱怨
tsan complaints with notify_all_at_thread_exit
当我运行从分离线程调用notify_all_at_thread_exit((的代码时,tsan 抱怨 pthread_cond_broadcast 和 pthread_cond_destroy 之间的数据争用。 我做错了什么吗? 或者这是 tsan 的误报?
#include <thread>
#include <chrono>
#include <mutex>
#include <condition_variable>
#include <iostream>
using namespace std;
using namespace std::chrono;
int main(int, char**){
mutex m;
condition_variable cv;
bool done = false;
thread([&](){
this_thread::sleep_for(milliseconds(100));
unique_lock<mutex> lk(m);
done = true;
notify_all_at_thread_exit(cv, std::move(lk));
}).detach();
unique_lock<mutex> lk(m);
cv.wait(lk, [&]{ return done; });
std::cout << "Donen";
return 0;
}
drdws0134$ garden with -m gcc/9.2.0-02c7/bin -- g++ -std=c++17 -fsanitize=thread bug1.cpp -O0 -ggdb -pthread && ./a.out
Done
==================
WARNING: ThreadSanitizer: data race (pid=27370)
Write of size 8 at 0x7ffd05131540 by main thread:
#0 pthread_cond_destroy /tmp/garden-install.88e036900cee/+tmp+/untar/gcc-9.2.0/libsanitizer/tsan/tsan_interceptors.cc:1171 (libtsan.so.0+0x30c66)
#1 main /u/nyc/salmonj/junk/thread_notify_bug/bug1.cpp:12 (a.out+0x402627)
Previous read of size 8 at 0x7ffd05131540 by thread T1:
#0 pthread_cond_broadcast /tmp/garden-install.88e036900cee/+tmp+/untar/gcc-9.2.0/libsanitizer/tsan/tsan_interceptors.cc:1164 (libtsan.so.0+0x30b63)
#1 __gthread_cond_broadcast /tmp/garden-install.88e036900cee/+tmp+/build/x86_64-pc-linux-gnu/libstdc++-v3/include/x86_64-pc-linux-gnu/bits/gthr-default.h:853 (libstdc++.so.6+0xd1ad8)
#2 std::condition_variable::notify_all() /tmp/garden-install.88e036900cee/+tmp+/untar/gcc-9.2.0/libstdc++-v3/src/c++11/condition_variable.cc:73 (libstdc++.so.6+0xd1ad8)
Location is stack of main thread.
Location is global '<null>' at 0x000000000000 ([stack]+0x00000001e540)
Thread T1 (tid=27372, finished) created by main thread at:
#0 pthread_create /tmp/garden-install.88e036900cee/+tmp+/untar/gcc-9.2.0/libsanitizer/tsan/tsan_interceptors.cc:964 (libtsan.so.0+0x3057b)
#1 __gthread_create /tmp/garden-install.88e036900cee/+tmp+/build/x86_64-pc-linux-gnu/libstdc++-v3/include/x86_64-pc-linux-gnu/bits/gthr-default.h:663 (libstdc++.so.6+0xd6fe4)
#2 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /tmp/garden-install.88e036900cee/+tmp+/untar/gcc-9.2.0/libstdc++-v3/src/c++11/thread.cc:135 (libstdc++.so.6+0xd6fe4)
#3 main /u/nyc/salmonj/junk/thread_notify_bug/bug1.cpp:15 (a.out+0x4025a4)
SUMMARY: ThreadSanitizer: data race /u/nyc/salmonj/junk/thread_notify_bug/bug1.cpp:12 in main
==================
ThreadSanitizer: reported 1 warnings
drdws0134$
FWIW,我从 tsan 使用 clang8 和 libc++ 收到非常相似的错误:
drdws0134$ garden with -m clang/8.0.0-06c7/bin -- clang++ -Wl,-rpath,/gdn/centos7/0001/x3/prefixes/clang/8.0.0-06c7__4bf264b1013a/lib -stdlib=libc++ -std=c++17 -fsanitize=thread bug1.cpp -O0 -ggdb -pthread && ./a.out
Done
==================
WARNING: ThreadSanitizer: data race (pid=27396)
Write of size 8 at 0x7ffea2b603e8 by main thread:
#0 pthread_cond_destroy /tmp/garden-install.d86e7e77c946/clang-8.0.0-06c7/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc:1216 (a.out+0x46b7b1)
#1 main /u/nyc/salmonj/junk/thread_notify_bug/bug1.cpp:26 (a.out+0x4c69b1)
Previous read of size 8 at 0x7ffea2b603e8 by thread T1:
#0 pthread_cond_broadcast /tmp/garden-install.d86e7e77c946/clang-8.0.0-06c7/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc:1209 (a.out+0x46b6bd)
#1 std::__1::__thread_struct_imp::~__thread_struct_imp() /tmp/garden-install.d86e7e77c946/clang-8.0.0-06c7/libcxx/src/thread.cpp:173 (libc++.so.1+0x8b17d)
Location is stack of main thread.
Location is global '<null>' at 0x000000000000 ([stack]+0x00000001e3e8)
Thread T1 (tid=27398, finished) created by main thread at:
#0 pthread_create /tmp/garden-install.d86e7e77c946/clang-8.0.0-06c7/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc:980 (a.out+0x452aa6)
#1 std::__1::__libcpp_thread_create(unsigned long*, void* (*)(void*), void*) /gdn/centos7/0001/x3/prefixes/clang/8.0.0-06c7__4bf264b1013a/bin/../include/c++/v1/__threading_support:328 (a.out+0x4c7eec)
#2 thread<(lambda at bug1.cpp:15:12), void> /gdn/centos7/0001/x3/prefixes/clang/8.0.0-06c7__4bf264b1013a/bin/../include/c++/v1/thread:368 (a.out+0x4c6b65)
#3 main /u/nyc/salmonj/junk/thread_notify_bug/bug1.cpp:15 (a.out+0x4c6922)
SUMMARY: ThreadSanitizer: data race /u/nyc/salmonj/junk/thread_notify_bug/bug1.cpp:26 in main
==================
ThreadSanitizer: reported 1 warnings
drdws0134$
是的,我相信可能存在竞争条件。
std::notify_all_at_thread_exit
被指定为在线程退出时执行等效的lk.unlock(); cv.notify_all()
。 如果您的主线程在解锁m
后立即遇到虚假唤醒,那么它会看到done
true
,并且可能会到达main
的末尾并在调用cv.notify_all()
之前销毁cv
。
相关文章:
- 静态代码检查器抱怨.虚惊一场?
- 我如何测试代码没有调用 exit()
- exit(0) 和 raise(SIGTERM) 有什么区别?
- 为什么 g++ 10.1 抱怨头文件中的命名 lambda,而其他人则没有?
- "Program ended with exit code: 0"出现在我的输出的开头?
- 为什么编译器在使用"无常量复制构造函数"时抱怨?
- 使用 GraphicsPath::AddString() 抱怨"class 'GraphicsPath' has no member 'AddString'"
- 为什么编译器抱怨 std::thread 参数在转换为右值后必须是可调用的?
- C++编译器抱怨没有默认构造函数
- cppcheck 抱怨危险地使用 c_str(). c_str() 返回的值在此调用后无效
- cpp 检查抱怨危险使用 c_str(). c_str() 返回的值在本次调用后无效,如何解决?
- 当我尝试进行TPC-E测试时,实用程序抱怨"undefined reference"
- 曾与notify_all_at_thread_exit抱怨
- exit(EXITT_FAILURE)在c和c++中是如何工作的
- 在C++中使用exit()退出程序有问题吗
- 什么时候在 c++ 中使用 exit() 与异常更好?
- "ndk-build finish with non-zero exit value 2" 在编译文本仙女项目时
- 当可以返回错误/异常时,从库中终止调用程序(例如,调用exit())是否总是错误的?
- 我在C++中收到错误" [Error] ld returned 1 exit status".帮我解决这个问题
- 为什么错误"permission denied","id returned 1 exit status"仅在 IM 使用 C++ 中的头文件 fstream 时才出现