Я озадачен отчетом о дезинфекции потоков, который появляется как для G CC 8, так и для Clang 9 (другие я не пробовал). Существует структура Bar
со следующим кодом:
struct Bar {
Bar(bool create_foo) {
...
if (create_foo) {
mFoo = new Foo();
mFooThread = std::thread(&Foo::Run, mFoo); // This is a Data Race?!?!?!?
mOther->setFoo(mFoo);
}
...
}
~Bar() {
if (mFooThread.joinable()) mFooThread.join();
}
Foo * mFoo;
std::thread mFooThread;
Other * mOther;
}
Запуск средства очистки потока в Ubuntu 18.04 с обоими компиляторами говорит, что строка создания потока (см. Комментарий выше) является гонкой данных. Единственное другое место, где используется этот поток (mFooThread
), - деструктор Bar
.
Чтобы дать больше подробностей ... дезинфицирующее средство потока сообщает 18 ошибок. 2 из них, похоже, не имеют никакого отношения к текущему проекту. Остальные все указывают на эту линию. Смущает то, что ошибки, похоже, не указывают ни на какую другую часть кодовой базы. Кажется, они просто указывают на эту линию. В программе создается только один объект Bar
, что заставляет меня задуматься, почему я вижу 16 ошибок.
2 ошибки, которые, я считаю, не связаны с проектом:
Lock-order-inversion (potential deadlock) (pid=3891)
Mutex M2925 acquired here while holding mutex M2921 in main thread:
pthread_mutex_lock
CPLAcquireMutex
Mutex M2921 acquired here while holding mutex M2925 in main thread:
pthread_mutex_lock
CPLCreateOrAcquireMutexEx
Lock-order-inversion (potential deadlock) (pid=3891)
Mutex M2922 acquired here while holding mutex M2921 in main thread:
pthread_mutex_lock
CPLAcquireMutex
Mutex M2921 acquired here while holding mutex M2922 in main thread:
pthread_mutex_lock
CPLCreateOrAcquireMutexEx
Для справки, это проект Cmake, который я не создавал, но, похоже, в нем есть некоторые Проблемы с потоками, так как пользователи сообщают, что программа случайно зависает. Я включил средство очистки потока следующим образом:
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=${sanitize}")
set(CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=${sanitize}")
РЕДАКТИРОВАТЬ:
Ниже приведен вывод TSAN для одного из предупреждений о гонке данных. Все они очень похожи:
Write of size 8 at 0x7b5000018500 by thread T29:
memset
g_slice_alloc0
Previous write of size 8 at 0x7b5000018500 by thread T15 (mutexes: write M3854):
posix_memalign
(libglib-2.0.so.0+0x690e6)
void std::__invoke_impl<void, void (Foo::*)(), Foo*>(std::__invoke_memfun_deref, void (Foo::*&&)(), Foo*&&)
std::__invoke_result<void (Foo::*)(), Foo*>::type std::__invoke<void (Foo::*)(), Foo*>(void (Foo::*&&)(), Foo*&&)
decltype(std::__invoke(_S_declval<0ul>(), _S_declval<1ul>())) std::thread::_Invoker<std::tuple>::_M_invoke<0ul, 1ul>(std::_Index_tuple<0ul, 1ul>)
std::thread::_Invoker<std::tuple>::operator()()
std::thread::_State_impl<std::thread::_Invoker>::_M_run()
(libstdc++.so.6+0xbd6de)
Location is heap block of size 496 at 0x7b5000018400 allocated by thread T15:
posix_memalign
(libglib-2.0.so.0+0x690e6)
void std::__invoke_impl<void, void (Foo::*)(), Foo*>(std::__invoke_memfun_deref, void (Foo::*&&)(), Foo*&&)
std::__invoke_result<void (Foo::*)(), Foo*>::type std::__invoke<void (Foo::*)(), Foo*>(void (Foo::*&&)(), Foo*&&)
decltype(std::__invoke(_S_declval<0ul>(), _S_declval<1ul>())) std::thread::_Invoker<std::tuple>::_M_invoke<0ul, 1ul>(std::_Index_tuple<0ul, 1ul>)
std::thread::_Invoker<std::tuple>::operator()()
std::thread::_State_impl<std::thread::_Invoker>::_M_run()
(libstdc++.so.6+0xbd6de)
Mutex M3854 (0x7b0c00536f70) created at:
pthread_mutex_init
(libglib-2.0.so.0+0x91e2c)
void std::__invoke_impl<void, void (Foo::*)(), Foo*>(std::__invoke_memfun_deref, void (Foo::*&&)(), Foo*&&)
std::__invoke_result<void (Foo::*)(), Foo*>::type std::__invoke<void (Foo::*)(), Foo*>(void (Foo::*&&)(), Foo*&&)
decltype(std::__invoke(_S_declval<0ul>(), _S_declval<1ul>())) std::thread::_Invoker<std::tuple>::_M_invoke<0ul, 1ul>(std::_Index_tuple<0ul, 1ul>)
std::thread::_Invoker<std::tuple>::operator()()
std::thread::_State_impl<std::thread::_Invoker>::_M_run()
(libstdc++.so.6+0xbd6de)
Thread T29 'gdbus' (tid=5438, running) created by thread T15 at:
pthread_create
(libglib-2.0.so.0+0x9240f)
void std::__invoke_impl<void, void (Foo::*)(), Foo*>(std::__invoke_memfun_deref, void (Foo::*&&)(), Foo*&&)
std::__invoke_result<void (Foo::*)(), Foo*>::type std::__invoke<void (Foo::*)(), Foo*>(void (Foo::*&&)(), Foo*&&)
decltype(std::__invoke(_S_declval<0ul>(), _S_declval<1ul>())) std::thread::_Invoker<std::tuple>::_M_invoke<0ul, 1ul>(std::_Index_tuple<0ul, 1ul>)
std::thread::_Invoker<std::tuple>::operator()()
std::thread::_State_impl<std::thread::_Invoker>::_M_run()
(libstdc++.so.6+0xbd6de)
Thread T15 (tid=5423, running) created by main thread at:
pthread_create
std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete>, void (*)())
Bar::Bar(bool)
main