Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-134689

Segmentation fault on accessing qt_signal_spy_callback_set.

    XMLWordPrintable

Details

    • Bug
    • Resolution: Invalid
    • Not Evaluated
    • None
    • 6.7.3
    • Core: Object Model
    • None
    • Yocto Linux, arm64
    • Linux/Yocto

    Description

      When my Qt Application is set up for testing with Squish, from time to time I experience a segmentation fault in `doActivate` method.

      Those are the backtraces from 2 threads:

      1) the one that crashes:

      #0  0x0000ffffaea9e100 in doActivate<true> (sender=0xaaab0e771420, signal_index=35,
          argv=0xffff47ffe278) at /usr/src/debug/qtbase/6.7.3-r0/git/src/corelib/kernel/qobject.cpp:3988
      #1  0x0000ffffb0253428 in QSGBatchRenderer::Renderer::render (this=0xffff3c2f79b0)
          at /usr/src/debug/qtdeclarative/6.7.3-r0/git/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp:3617
      #2  QSGBatchRenderer::Renderer::render (this=0xffff3c2f79b0)
          at /usr/src/debug/qtdeclarative/6.7.3-r0/git/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp:3609
      #3  0x0000ffffb0267750 in QSGRenderer::renderScene (this=0xffff3c2f79b0)
          at /usr/src/debug/qtdeclarative/6.7.3-r0/git/src/quick/scenegraph/coreapi/qsgrenderer.cpp:143
      #4  QSGRenderer::renderScene (this=0xffff3c2f79b0)
          at /usr/src/debug/qtdeclarative/6.7.3-r0/git/src/quick/scenegraph/coreapi/qsgrenderer.cpp:118
      #5  0x0000ffffb0210d60 in QQuickWindowPrivate::renderSceneGraph (this=this@entry=0xaaab0e749fb0)
          at /usr/src/debug/qtdeclarative/6.7.3-r0/git/src/quick/items/qquickwindow.cpp:666
      #6  0x0000ffffb03ffde4 in QSGRenderThread::syncAndRender (this=this@entry=0xaaab0f00f340)
          at /usr/src/debug/qtdeclarative/6.7.3-r0/git/src/quick/scenegraph/qsgthreadedrenderloop.cpp:761
      #7  0x0000ffffb0400ee8 in QSGRenderThread::run (this=0xaaab0f00f340)
          at /usr/src/debug/qtdeclarative/6.7.3-r0/git/src/quick/scenegraph/qsgthreadedrenderloop.cpp:974
      #8  0x0000ffffaebe0678 in operator() (__closure=<optimized out>, __closure=<optimized out>)
          at /usr/src/debug/qtbase/6.7.3-r0/git/src/corelib/thread/qthread_unix.cpp:323
      #9  (anonymous namespace)::terminate_on_exception<QThreadPrivate::start(void*)::<lambda()> > (t=...,
          t=...) at /usr/src/debug/qtbase/6.7.3-r0/git/src/corelib/thread/qthread_unix.cpp:259
      #10 QThreadPrivate::start (arg=0xaaab0f00f340)
          at /usr/src/debug/qtbase/6.7.3-r0/git/src/corelib/thread/qthread_unix.cpp:282
      #11 0x0000ffffae550758 in start_thread (arg=0xffffe72ef487) at pthread_create.c:442
      #12 0x0000ffffae5b809c in thread_start () at ../sysdeps/unix/sysv/linux/aarch64/clone.S:79 

      2) and the squish one:

      #0  0x0000ffffae560f6c in __GI___libc_free (mem=0xaaab121f89c0) at malloc.c:3363
      #1  0x0000ffff8819219c in std::__cxx11::_List_base<QVariant, std::allocator<QVariant> >::_M_clear() () from /home/ptanski/cores_NWOTSW-38676/sysroot/mnt/appfs/nwot-appfs1/opt/qt/squish/lib/libsquishhook.so
      #2  0x0000ffff8823b0b8 in Squish::AsyncIPC::IncomingCall::finalize(QDataStream&) () from /home/ptanski/cores_NWOTSW-38676/sysroot/mnt/appfs/nwot-appfs1/opt/qt/squish/lib/libsquishhook.so
      #3  0x0000ffff88236478 in Squish::AsyncIPC::onMessageArrived(QByteArray) () from /home/ptanski/cores_NWOTSW-38676/sysroot/mnt/appfs/nwot-appfs1/opt/qt/squish/lib/libsquishhook.so
      #4  0x0000ffff88245bb0 in Squish::AsyncIPC::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) ()
         from /home/ptanski/cores_NWOTSW-38676/sysroot/mnt/appfs/nwot-appfs1/opt/qt/squish/lib/libsquishhook.so
      #5  0x0000ffffaea9e208 in doActivate<true> (sender=0xaaab1173f160, signal_index=3, argv=0xffffe72ef900) at /usr/src/debug/qtbase/6.7.3-r0/git/src/corelib/kernel/qobject.cpp:4098
      #6  0x0000ffff882468f4 in Squish::AsyncMessageChannel::messageArrived(QByteArray) () from /home/ptanski/cores_NWOTSW-38676/sysroot/mnt/appfs/nwot-appfs1/opt/qt/squish/lib/libsquishhook.so
      #7  0x0000ffff8823cac8 in Squish::TCPMessageChannel::processSingleMessage(QByteArray*) () from /home/ptanski/cores_NWOTSW-38676/sysroot/mnt/appfs/nwot-appfs1/opt/qt/squish/lib/libsquishhook.so
      #8  0x0000ffff8823d178 in Squish::TCPMessageChannel::dispatchMessages(bool) () from /home/ptanski/cores_NWOTSW-38676/sysroot/mnt/appfs/nwot-appfs1/opt/qt/squish/lib/libsquishhook.so
      #9  0x0000ffffaea9e208 in doActivate<true> (sender=0xaaab1173f6c0, signal_index=5, argv=0xffffe72efb20) at /usr/src/debug/qtbase/6.7.3-r0/git/src/corelib/kernel/qobject.cpp:4098
      #10 0x0000ffffaea961c0 in QMetaObject::activate (sender=sender@entry=0xaaab1173f6c0, m=<optimized out>, local_signal_index=local_signal_index@entry=2, argv=argv@entry=0xffffe72efb20)
          at /usr/src/debug/qtbase/6.7.3-r0/git/src/corelib/kernel/qobject.cpp:4144
      #11 0x0000ffffaeaab7a0 in QSocketNotifier::activated (this=this@entry=0xaaab1173f6c0, _t1=<optimized out>, _t2=_t2@entry=...)
          at /usr/src/debug/qtbase/6.7.3-r0/build/src/corelib/Core_autogen/include/moc_qsocketnotifier.cpp:202
      #12 0x0000ffffaeaac12c in QSocketNotifier::event (this=0xaaab1173f6c0, e=<optimized out>) at /usr/src/debug/qtbase/6.7.3-r0/git/src/corelib/kernel/qsocketnotifier.h:82
      #13 0x0000ffffb0c73290 in QApplicationPrivate::notify_helper (this=<optimized out>, receiver=0xaaab1173f6c0, e=0xffffe72efc58) at /usr/src/debug/qtbase/6.7.3-r0/git/src/widgets/kernel/qapplication.cpp:3287
      #14 0x0000ffffaea3ab30 in QCoreApplication::notifyInternal2 (receiver=0xaaab1173f6c0, event=event@entry=0xffffe72efc58) at /usr/src/debug/qtbase/6.7.3-r0/git/src/corelib/kernel/qcoreapplication.cpp:1152
      #15 0x0000ffffaea3ae1c in QCoreApplication::sendEvent (receiver=<optimized out>, event=event@entry=0xffffe72efc58) at /usr/src/debug/qtbase/6.7.3-r0/git/src/corelib/kernel/qcoreapplication.cpp:1593
      #16 0x0000ffffaed040cc in socketNotifierSourceDispatch (source=0xaaab0e20fa10) at /usr/src/debug/qtbase/6.7.3-r0/git/src/corelib/kernel/qeventdispatcher_glib.cpp:75
      #17 0x0000ffffadb982c8 in g_main_dispatch (context=0xffffa4005030) at ../glib-2.72.3/glib/gmain.c:3417
      #18 g_main_context_dispatch (context=0xffffa4005030) at ../glib-2.72.3/glib/gmain.c:4135
      #19 0x0000ffffadb98568 in g_main_context_iterate (context=context@entry=0xffffa4005030, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at ../glib-2.72.3/glib/gmain.c:4211
      #20 0x0000ffffadb98648 in g_main_context_iteration (context=0xffffa4005030, may_block=1) at ../glib-2.72.3/glib/gmain.c:4276
      #21 0x0000ffffaed02f18 in QEventDispatcherGlib::processEvents (this=0xaaab0e2075f0, flags=...) at /usr/src/debug/qtbase/6.7.3-r0/git/src/corelib/kernel/qeventdispatcher_glib.cpp:394
      #22 0x0000ffffaea476cc in QEventLoop::exec (this=this@entry=0xffffe72efea0, flags=flags@entry=...) at /usr/src/debug/qtbase/6.7.3-r0/git/src/corelib/global/qflags.h:34
      #23 0x0000ffffaea43440 in QCoreApplication::exec () at /usr/src/debug/qtbase/6.7.3-r0/git/src/corelib/global/qflags.h:74
      #24 0x0000ffffaf2cd518 in QGuiApplication::exec () at /usr/src/debug/qtbase/6.7.3-r0/git/src/gui/kernel/qguiapplication.cpp:1932
      #25 0x0000ffffb0c73228 in QApplication::exec () at /usr/src/debug/qtbase/6.7.3-r0/git/src/widgets/kernel/qapplication.cpp:2555
      #26 0x0000aaaae948ba58 in QtAM::Main::exec () at /usr/src/debug/qtapplicationmanager/6.7.3-r0/git/src/main-lib/main.cpp:307
      #27 0x0000aaaae946cd6c in main (argc=<optimized out>, argv=<optimized out>) at /usr/src/debug/system-ui/AUTOINC+09d3deb0fc-r0/git/src/impl/main.cpp:183 

      I see that `doActivate` is called with `callbacks_enabled` set to true. This is decided here:

          if (Q_UNLIKELY(qt_signal_spy_callback_set.loadRelaxed()))
              doActivate<true>(sender, signal_index, argv);
          else
              doActivate<false>(sender, signal_index, argv); 

      And that's the code of doActivate from Qt 6.7.3:

      template <bool callbacks_enabled>
      void doActivate(QObject *sender, int signal_index, void **argv)
      {
          QObjectPrivate *sp = QObjectPrivate::get(sender);
      
          if (sp->blockSig)
              return;
      
          Q_TRACE_SCOPE(QMetaObject_activate, sender, signal_index);
      
          if (sp->isDeclarativeSignalConnected(signal_index)
                  && QAbstractDeclarativeData::signalEmitted) {
              Q_TRACE_SCOPE(QMetaObject_activate_declarative_signal, sender, signal_index);
              QAbstractDeclarativeData::signalEmitted(sp->declarativeData, sender,
                                                      signal_index, argv);
          }
      
          const QSignalSpyCallbackSet *signal_spy_set = callbacks_enabled ? qt_signal_spy_callback_set.loadAcquire() : nullptr;
      
          void *empty_argv[] = { nullptr };
          if (!argv)
              argv = empty_argv;
      
          if (!sp->maybeqt_signal_spy_callback_setSignalConnected(signal_index)) {
              // The possible declarative connection is done, and nothing else is connected
              if (callbacks_enabled && signal_spy_set->signal_begin_callback != nullptr)
                  signal_spy_set->signal_begin_callback(sender, signal_index, argv);
              if (callbacks_enabled && signal_spy_set->signal_end_callback != nullptr)
                  signal_spy_set->signal_end_callback(sender, signal_index);
              return;
          } 

      The crash occurs on this line:

      if (callbacks_enabled && signal_spy_set->signal_begin_callback != nullptr)

      From the coredump I was able to deduce that:

      (gdb) print callbacks_enabled
      $26 = true
      (gdb) print signal_spy_set
      $27 = (const QSignalSpyCallbackSet *) 0x0 

      Even though the callbacks_enabled is set to true, the signal_spy_set is a nullptr. There’s a null pointer dereference in such a case, because there's only a check for callbacks_enabled  but no check for signal_spy_set != nullptr.

      Squish manipulates with the qt_signal_spy_callback_set in its SignalCatcher using:

      void qt_register_signal_spy_callbacks(QSignalSpyCallbackSet *callback_set)
      {
          qt_signal_spy_callback_set.storeRelease(callback_set);
      } 

      I assume that Squish reset the qt_signal_spy_callback_set to nullptr when the main thread was somewhere in between 

      Q_UNLIKELY(qt_signal_spy_callback_set.loadRelaxed()) 

      and

      const QSignalSpyCallbackSet *signal_spy_set = callbacks_enabled ? qt_signal_spy_callback_set.loadAcquire() : nullptr; 

      This may happen because loadRelaxed() does not impose any synchronization.

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            thiago Thiago Macieira
            piotrtanski Piotr Tański
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes