Создание отчетов о дезинфекции потоков с помощью QCoreApplication :: postEvent () при вызове полученного экземпляра события - PullRequest
2 голосов
/ 12 марта 2020

У меня следующий код:

std::thread   thread;
EventReceiver target;

{
   thread = std::thread([&]() {
        auto event = new MyEvent();
        QCoreApplication::postEvent(&target, event);
      }
    });

   IdleProcessor::processEvents();
   thread.join();
}

Где

class MyEvent : public QEvent, public async::ExecutorEventInterface
{
public:
    MyEvent()
        : QEvent(QEvent::User){

          };

    void execute() override
    {
    }
};

class EventReceiver : public QObject
{
    Q_OBJECT
public:
    EventReceiver();

    /**
     * @brief receives the MainExecutor posted event
     * @param event
     * @return
     */
    bool event(QEvent* event) override
    {
        auto myEvent = dynamic_cast<ExecutorEventInterface*>(event);
        if (myEvent)
        {
           myEvent->execute();
           return true;
        }
        return false;
    }
};

Я получаю отчет о дезинфекции нитей и не понимаю, почему.

==================
WARNING: ThreadSanitizer: data race on vptr (ctor/dtor vs virtual call) (pid=56278)
  Read of size 8 at 0x7b0800026018 by main thread:
    #0 async::EventReceiver::event(QEvent*) eventreceiver.cpp:16 (unittests:x86_64+0x107353775)
    #1 QCoreApplicationPrivate::notify_helper(QObject*, QEvent*) <null> (QtCore:x86_64+0x1ea917)
    #2 AsyncTest_test_Test::TestBody() async_tests.cpp:103 (unittests:x86_64+0x1004fa8f3)
    #3 void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) <null> (unittests:x86_64+0x1042addbd)
    #4 TestApplication::event(QEvent*) testapplication.cpp:20 (unittests:x86_64+0x1041f89cf)
    #5 QCoreApplicationPrivate::notify_helper(QObject*, QEvent*) <null> (QtCore:x86_64+0x1ea917)
    #6 start <null> (libdyld.dylib:x86_64+0x163d4)

  Previous write of size 8 at 0x7b0800026018 by thread T4:
    #0 async::ExecutorEventInterface::ExecutorEventInterface() executoreventinterface.h:9 (unittests:x86_64+0x10058dd10)
    #1 MyEvent::MyEvent() async_tests.cpp:73 (unittests:x86_64+0x100599466)
    #2 MyEvent::MyEvent() async_tests.cpp:74 (unittests:x86_64+0x1005993e8)
    #3 AsyncTest_test_Test::TestBody()::$_6::operator()() const async_tests.cpp:98 (unittests:x86_64+0x100599322)
    #4 void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, AsyncTest_test_Test::TestBody()::$_6> >(void*) type_traits:4428 (unittests:x86_64+0x100598fb5)

  Location is heap block of size 32 at 0x7b0800026000 allocated by thread T4:
    #0 operator new(unsigned long) <null> (libclang_rt.tsan_osx_dynamic.dylib:x86_64h+0x6d723)
    #1 AsyncTest_test_Test::TestBody()::$_6::operator()() const async_tests.cpp:98 (unittests:x86_64+0x100599308)
    #2 void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, AsyncTest_test_Test::TestBody()::$_6> >(void*) type_traits:4428 (unittests:x86_64+0x100598fb5)

  Thread T4 (tid=424005, finished) created by main thread at:
    #0 pthread_create <null> (libclang_rt.tsan_osx_dynamic.dylib:x86_64h+0x2936d)
    #1 std::__1::thread::thread<AsyncTest_test_Test::TestBody()::$_6, void>(AsyncTest_test_Test::TestBody()::$_6&&) __threading_support:336 (unittests:x86_64+0x100598642)
    #2 std::__1::thread::thread<AsyncTest_test_Test::TestBody()::$_6, void>(AsyncTest_test_Test::TestBody()::$_6&&) thread:360 (unittests:x86_64+0x1004faa88)
    #3 AsyncTest_test_Test::TestBody() async_tests.cpp:94 (unittests:x86_64+0x1004fa81e)
    #4 void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) <null> (unittests:x86_64+0x1042addbd)
    #5 TestApplication::event(QEvent*) testapplication.cpp:20 (unittests:x86_64+0x1041f89cf)
    #6 QCoreApplicationPrivate::notify_helper(QObject*, QEvent*) <null> (QtCore:x86_64+0x1ea917)
    #7 start <null> (libdyld.dylib:x86_64+0x163d4)

SUMMARY: ThreadSanitizer: data race on vptr (ctor/dtor vs virtual call) eventreceiver.cpp:16 in async::EventReceiver::event(QEvent*)

Почему это происходит, если учесть, что EventReceiver создан в потоке, а затем размещен в главном потоке, похоже, это гонка при выполнении виртуального метода, но в этот момент объект полностью создан.

ПОЗДНЕЕ РЕДАКТИРОВАНИЕ Это похоже на добрую гонку. Средство очистки не знает / не видит, что EventReceiver :: event (QEvent * event) происходит после / вызвано использованием QCoreApplication :: postEvent (& target, event), что происходит после создания MyEvent (поскольку экземпляр MyEvent вводится в QCoreApplication :: postEvent)

Я могу добавить явное ограждение для того, чтобы это было ясно для дезинфицирующего средства, но это кажется чрезмерным? Интересно, рекомендуется ли использовать некоторые аннотации, чтобы отключить это?

...