首页 > 解决方案 > 为什么 ThreadSanitizer (TSAN) 在 Glib::signal_idle().connect_once 上报告数据竞争

问题描述

hello.cpp 的内容

#include <gtkmm.h>

void RunInMain()
{
    printf("RunInMain\n");
}

void ThreadFunc()
{
    printf("ThreadFunc\n");
    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

这是执行生成的 a.out 文件时来自 TSAN 的错误:

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 31 linux
g++ 10.0.1
glibmm24-2.64.2-1
gtkmm24-2.24.5-9
libtsan-10.2.1-9

标签: c++multithreadinggtkgtkmmthread-sanitizer

解决方案


推荐阅读