Details
-
Bug
-
Resolution: Invalid
-
Not Evaluated
-
None
-
6.7.3
-
None
-
Yocto Linux, arm64
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.