hello.cpp目录
#include <gtkmm.h>
void RunInMain()
{
printf("RunInMainn");
}
void ThreadFunc()
{
printf("ThreadFuncn");
Glib::signal_idle().connect_once(std::bind(&RunInMain));
}
int main()
{
Gtk::Main kit(0, NULL);
Gtk::Window window;
window.set_title("hello world");
Glib::Thread* pThread = Glib::Thread::create(&ThreadFunc);
kit.run(window);
pThread->join();
return(0);
}
编译:
g++ `pkg-config gtkmm-2.4 --cflags --libs` hello.cpp -Wno-deprecated-declarations -fsanitize=thread
这是TSAN在执行结果a.out文件时的错误:
WARNING: ThreadSanitizer: data race (pid=153699)
Write of size 8 at 0x7b5000006f90 by thread T1:
#0 memset <null> (libtsan.so.0+0x37abf)
#1 g_slice_alloc0 <null> (libglib-2.0.so.0+0x71412)
#2 sigc::pointer_functor0<void>::operator()() const <null> (a.out+0x402835)
#3 sigc::adaptor_functor<sigc::pointer_functor0<void> >::operator()() const <null> (a.out+0x402606)
#4 sigc::internal::slot_call0<void (*)(), void>::call_it(sigc::internal::slot_rep*) <null> (a.out+0x4021d0)
#5 call_thread_entry_slot /usr/include/sigc++-2.0/sigc++/functors/slot.h:535 (libglibmm-2.4.so.1+0x5d889)
Previous write of size 8 at 0x7b5000006f90 by main thread:
#0 posix_memalign <null> (libtsan.so.0+0x3061d)
#1 allocator_memalign ../glib/gslice.c:1411 (libglib-2.0.so.0+0x706b8)
#2 allocator_add_slab ../glib/gslice.c:1283 (libglib-2.0.so.0+0x706b8)
#3 slab_allocator_alloc_chunk ../glib/gslice.c:1329 (libglib-2.0.so.0+0x706b8)
#4 __libc_start_main ../csu/libc-start.c:308 (libc.so.6+0x27041)
Location is heap block of size 496 at 0x7b5000006e00 allocated by main thread:
#0 posix_memalign <null> (libtsan.so.0+0x3061d)
#1 allocator_memalign ../glib/gslice.c:1411 (libglib-2.0.so.0+0x706b8)
#2 allocator_add_slab ../glib/gslice.c:1283 (libglib-2.0.so.0+0x706b8)
#3 slab_allocator_alloc_chunk ../glib/gslice.c:1329 (libglib-2.0.so.0+0x706b8)
#4 __libc_start_main ../csu/libc-start.c:308 (libc.so.6+0x27041)
Thread T1 (tid=153701, running) created by main thread at:
#0 pthread_create <null> (libtsan.so.0+0x5ec29)
#1 g_system_thread_new ../glib/gthread-posix.c:1308 (libglib-2.0.so.0+0xa0ea0)
#2 __libc_start_main ../csu/libc-start.c:308 (libc.so.6+0x27041)
SUMMARY: ThreadSanitizer: data race (/lib64/libtsan.so.0+0x37abf) in memset
代码按预期运行(我得到了所有的打印),但我不明白为什么我得到了TSAN数据竞争警告。如果我注释掉Glib::signal_idle().connect_once行,没有TSAN错误。从我所读到的,这个函数应该是安全的,可以从任何线程调用。TSAN报告的是假阳性还是真正的数据竞赛?
Fedora linux 31日
g++ 10.0.1
glibmm24-2.64.2-1
gtkmm24-2.24.5-9
libtsan-10.2.1-9
From TSAN wiki:
TSAN通常要求使用-fsanitize=thread编译所有代码。如果某些代码(例如动态库)没有使用该标志编译,它可能导致假阳性竞争报告,假阴性竞争报告和/或报告中遗漏堆栈帧,这取决于非仪表代码的性质。
如果你使用的是来自发行版库的glib(例如:sudo apt get install libglib2.0-dev
),则误报报告的数量将取决于库的构建方式-警告的数量将因发行版而异。为了得到正确的TSAN报告,应该用-fsanitize=thread
手工编译所有使用的共享库。特别是glib应该手工编译,因为它包含各种与线程相关的api。
用TSAN编译glib (for Debian 11.5 "bullseye"):
# clone TAG 2.66.8 (TAG should match glib version on the host)
git clone --depth=1 --branch=2.66.8 https://github.com/GNOME/glib.git
cd glib
CFLAGS="-O2 -g -fsanitize=thread" meson build
ninja -C build
# add TSAN-enabled glib libraries to lib search path
export LD_LIBRARY_PATH=$PWD/build/gio:$PWD/build/glib:$PWD/build/gmodule:$PWD/build/gobject:$PWD/build/gthread
在运行你的项目之前,确保它链接到新编译的glib库(如果使用所有的glib库,即:libglib, libgio, libgmodule, libgobject, libgthread)与ldd a.out
。