Fix crash when initializing offscreen surface in GLWidget
ClosedPublic

Authored by dvratil on Mar 20 2018, 2:42 PM.

Details

Summary

GLWidget::initializeGL() is invoked in the renderer thread, but m_offscreenSurface lives in the
main thread (because it's constructed when GLWidget is constructed and GLWidget lives in the main
thread), which leads to an assert in Qt when m_offscreenSurface->create() is called from there
initializeGL(). Internally, QOffscreenSurface tries to send an event through QApplication, which
is only allowed from the thread in which the object lives and triggers an assert in Qt otherise (when
Qt is compiled in debug mode).

This fix moves creation of QOffscreenSurface to the GLWidget::initializeGL() method, which
ensures that the object is created and lives in the renderer thread.

BT of the crash:

Thread 11 (Thread 0x7fff62158700 (LWP 32060)):
#0  0x00007fffe8203660 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1  0x00007fffe8204c41 in __GI_abort () at abort.c:79
#2  0x00007fffe8f09e9c in qt_message_fatal(QtMsgType, QMessageLogContext const&, QString const&) (context=..., message="ASSERT failure in QCoreApplication::sendEvent: \"Cannot send events to objects owned by a different thread. Current thread 0x0x7fffcc02d120. Receiver '' (of type 'QOffscreenSurface') was created in thr"...)
    at /data/Qt/qt5/qtbase/src/corelib/global/qlogging.cpp:1839
#3  0x00007fffe8f0aac8 in QMessageLogger::fatal(char const*, ...) const (this=this@entry=0x7fff62157330, msg=msg@entry=0x7fffe9195138 "ASSERT failure in %s: \"%s\", file %s, line %d") at /data/Qt/qt5/qtbase/src/corelib/global/qlogging.cpp:877
#4  0x00007fffe8f04cca in qt_assert_x(char const*, char const*, char const*, int) (where=where@entry=0x7fffe91a4caa "QCoreApplication::sendEvent", what=<optimized out>, file=file@entry=0x7fffe919cb70 "/data/Qt/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp", line=line@entry=576) at /data/Qt/qt5/qtbase/src/corelib/global/qglobal.cpp:3188
#5  0x00007fffe90d33dd in QCoreApplicationPrivate::checkReceiverThread(QObject*) (receiver=receiver@entry=0x1e8d278) at /data/Qt/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:570
#6  0x00007ffff1869aea in QApplication::notify(QObject*, QEvent*) (this=0x7fffffffcd80, receiver=0x1e8d278, e=0x7fff62157600) at /data/Qt/qt5/qtbase/src/widgets/kernel/qapplication.cpp:2944
#7  0x00007fffe90d3900 in QCoreApplication::notifyInternal2(QObject*, QEvent*) (receiver=receiver@entry=0x1e8d278, event=event@entry=0x7fff62157600) at /data/Qt/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:1048
#8  0x00007fffe9499077 in QCoreApplication::sendEvent(QObject*, QEvent*) (event=0x7fff62157600, receiver=0x1e8d278) at ../../include/QtCore/../../../../qtbase/src/corelib/kernel/qcoreapplication.h:234
#9  0x00007fffe9499077 in QOffscreenSurface::create() (this=0x1e8d278) at /data/Qt/qt5/qtbase/src/gui/kernel/qoffscreensurface.cpp:213
#10 0x00000000008107d5 in GLWidget::initializeGL() (this=0x1e8d150) at /data/KDE/src/kde/kdemultimedia/kdenlive/src/monitor/glwidget.cpp:152
#11 0x000000000081dabe in QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, void (GLWidget::*)()>::call(void (GLWidget::*)(), GLWidget*, void**) (f=(void (GLWidget::*)(GLWidget * const)) 0x8106e4 <GLWidget::initializeGL()>, o=0x1e8d150, arg=0x7fff621579b8) at /data/install/qt5/include/QtCore/qobjectdefs_impl.h:134
#12 0x000000000081d7e6 in QtPrivate::FunctionPointer<void (GLWidget::*)()>::call<QtPrivate::List<>, void>(void (GLWidget::*)(), GLWidget*, void**) (f=(void (GLWidget::*)(GLWidget * const)) 0x8106e4 <GLWidget::initializeGL()>, o=0x1e8d150, arg=0x7fff621579b8) at /data/install/qt5/include/QtCore/qobjectdefs_impl.h:167
#13 0x000000000081cd73 in QtPrivate::QSlotObject<void (GLWidget::*)(), QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) (which=1, this_=0x22d0c40, r=0x1e8d150, a=0x7fff621579b8, ret=0x0) at /data/install/qt5/include/QtCore/qobjectdefs_impl.h:396
#14 0x00007fffe91033e7 in QtPrivate::QSlotObjectBase::call(QObject*, void**) (a=<optimized out>, r=0x1e8d150, this=0x22d0c40) at ../../include/QtCore/../../../../qtbase/src/corelib/kernel/qobjectdefs_impl.h:376
#15 0x00007fffe91033e7 in QMetaObject::activate(QObject*, int, int, void**) (sender=sender@entry=0x1e8d150, signalOffset=<optimized out>, local_signal_index=local_signal_index@entry=2, argv=argv@entry=0x0) at /data/Qt/qt5/qtbase/src/corelib/kernel/qobject.cpp:3752
#16 0x00007fffe9103879 in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) (sender=0x1e8d150, m=m@entry=0x7fffea492de0 <QQuickWindow::staticMetaObject>, local_signal_index=local_signal_index@entry=2, argv=argv@entry=0x0) at /data/Qt/qt5/qtbase/src/corelib/kernel/qobject.cpp:3631
#17 0x00007fffea1f2d1e in QQuickWindow::sceneGraphInitialized() (this=<optimized out>) at .moc/moc_qquickwindow.cpp:482
#18 0x00007fffea1f6b44 in QQuickWindow::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) (_o=_o@entry=0x1e8d150, _c=_c@entry=QMetaObject::InvokeMetaMethod, _id=_id@entry=2, _a=<optimized out>) at .moc/moc_qquickwindow.cpp:246
#19 0x00007fffe9103590 in QMetaObject::activate(QObject*, int, int, void**) (sender=sender@entry=0x138be60, signalOffset=<optimized out>, local_signal_index=local_signal_index@entry=0, argv=argv@entry=0x0) at /data/Qt/qt5/qtbase/src/corelib/kernel/qobject.cpp:3769
#20 0x00007fffe9103879 in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) (sender=sender@entry=0x138be60, m=m@entry=0x7fffea48df80 <QSGRenderContext::staticMetaObject>, local_signal_index=local_signal_index@entry=0, argv=argv@entry=0x0) at /data/Qt/qt5/qtbase/src/corelib/kernel/qobject.cpp:3631
#21 0x00007fffea16ef4a in QSGRenderContext::initialized() (this=this@entry=0x138be60) at .moc/moc_qsgcontext_p.cpp:212
#22 0x00007fffea18dc78 in QSGDefaultRenderContext::initialize(void*) (this=0x138be60, context=<optimized out>) at /data/Qt/qt5/qtdeclarative/src/quick/scenegraph/qsgdefaultrendercontext.cpp:111
#23 0x00007fffea199c86 in QSGRenderThread::run() (this=0x7fffcc02d120) at /data/Qt/qt5/qtdeclarative/src/quick/scenegraph/qsgthreadedrenderloop.cpp:728
#24 0x00007fffe8f2178e in QThreadPrivate::start(void*) (arg=0x7fffcc02d120) at /data/Qt/qt5/qtbase/src/corelib/thread/qthread_unix.cpp:367
#25 0x00007fffe6c5450b in start_thread (arg=0x7fff62158700) at pthread_create.c:465
#26 0x00007fffe82c416f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95

(skipped irrelevant threads)

Thread 1 (Thread 0x7fffdb2e2100 (LWP 32038)):
#0  0x00007fffe6c5a82d in futex_wait_cancelable (private=<optimized out>, expected=0, futex_word=0x38200f0) at ../sysdeps/unix/sysv/linux/futex-internal.h:88
#1  0x00007fffe6c5a82d in __pthread_cond_wait_common (abstime=0x0, mutex=0x38200a0, cond=0x38200c8) at pthread_cond_wait.c:502
#2  0x00007fffe6c5a82d in __pthread_cond_wait (cond=0x38200c8, mutex=0x38200a0) at pthread_cond_wait.c:655
#3  0x00007fffe8f21d65 in QWaitConditionPrivate::wait(unsigned long) (time=18446744073709551615, this=0x38200a0) at /data/Qt/qt5/qtbase/src/corelib/thread/qwaitcondition_unix.cpp:143
#4  0x00007fffe8f21d65 in QWaitCondition::wait(QMutex*, unsigned long) (this=<optimized out>, mutex=0x7fffcc02d160, time=time@entry=18446744073709551615) at /data/Qt/qt5/qtbase/src/corelib/thread/qwaitcondition_unix.cpp:215
#5  0x00007fffea1974a9 in QSGThreadedRenderLoop::polishAndSync(QSGThreadedRenderLoop::Window*, bool) (this=this@entry=0x2781470, w=w@entry=0x3844c30, inExpose=inExpose@entry=true) at /data/Qt/qt5/qtdeclarative/src/quick/scenegraph/qsgthreadedrenderloop.cpp:1210
#6  0x00007fffea1991da in QSGThreadedRenderLoop::handleExposure(QQuickWindow*) (this=this@entry=0x2781470, window=window@entry=0x1e8d150) at /data/Qt/qt5/qtdeclarative/src/quick/scenegraph/qsgthreadedrenderloop.cpp:1004
#7  0x00007fffea199682 in QSGThreadedRenderLoop::exposureChanged(QQuickWindow*) (this=0x2781470, window=0x1e8d150) at /data/Qt/qt5/qtdeclarative/src/quick/scenegraph/qsgthreadedrenderloop.cpp:915
#8  0x00007fffea1f26d8 in QQuickWindow::exposeEvent(QExposeEvent*) (this=<optimized out>) at /data/Qt/qt5/qtdeclarative/src/quick/items/qquickwindow.cpp:226
#9  0x00007fffe9498473 in QWindow::event(QEvent*) (this=this@entry=0x1e8d150, ev=ev@entry=0x7fffffffcaf0) at /data/Qt/qt5/qtbase/src/gui/kernel/qwindow.cpp:2302
#10 0x00007fffea202081 in QQuickWindow::event(QEvent*) (this=0x1e8d150, e=0x7fffffffcaf0) at /data/Qt/qt5/qtdeclarative/src/quick/items/qquickwindow.cpp:1628
#11 0x00007ffff1862c6f in QApplicationPrivate::notify_helper(QObject*, QEvent*) (this=this@entry=0xe516d0, receiver=receiver@entry=0x1e8d150, e=e@entry=0x7fffffffcaf0) at /data/Qt/qt5/qtbase/src/widgets/kernel/qapplication.cpp:3713
#12 0x00007ffff1869dfc in QApplication::notify(QObject*, QEvent*) (this=0x7fffffffcd80, receiver=0x1e8d150, e=0x7fffffffcaf0) at /data/Qt/qt5/qtbase/src/widgets/kernel/qapplication.cpp:3085
#13 0x00007fffe90d3900 in QCoreApplication::notifyInternal2(QObject*, QEvent*) (receiver=receiver@entry=0x1e8d150, event=event@entry=0x7fffffffcaf0) at /data/Qt/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:1048
#14 0x00007fffe948d207 in QCoreApplication::sendSpontaneousEvent(QObject*, QEvent*) (event=0x7fffffffcaf0, receiver=0x1e8d150) at ../../include/QtCore/../../../../qtbase/src/corelib/kernel/qcoreapplication.h:237
#15 0x00007fffe948d207 in QGuiApplicationPrivate::processExposeEvent(QWindowSystemInterfacePrivate::ExposeEvent*) (e=<optimized out>) at /data/Qt/qt5/qtbase/src/gui/kernel/qguiapplication.cpp:3013
#16 0x00007fffe948dd85 in QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent*) (e=e@entry=0x25b1c70) at /data/Qt/qt5/qtbase/src/gui/kernel/qguiapplication.cpp:1849
#17 0x00007fffe94661f3 in QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>) (flags=...) at /data/Qt/qt5/qtbase/src/gui/kernel/qwindowsysteminterface.cpp:1028
#18 0x00007fffd3b866fd in QPAEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) (this=0xec0a20, flags=...) at /data/Qt/qt5/qtbase/src/platformsupport/eventdispatchers/qeventdispatcher_glib.cpp:70
#19 0x00007fffe90d1a21 in QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) (this=this@entry=0x7fffffffcc90, flags=..., flags@entry=...) at /data/Qt/qt5/qtbase/src/corelib/kernel/qeventloop.cpp:136
#20 0x00007fffe90d1e36 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) (this=this@entry=0x7fffffffcc90, flags=flags@entry=...) at /data/Qt/qt5/qtbase/src/corelib/kernel/qeventloop.cpp:214
#21 0x00007fffe90db76e in QCoreApplication::exec() () at /data/Qt/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:1336
#22 0x00007fffe9483a1e in QGuiApplication::exec() () at /data/Qt/qt5/qtbase/src/gui/kernel/qguiapplication.cpp:1729
#23 0x00007ffff1862b4f in QApplication::exec() () at /data/Qt/qt5/qtbase/src/widgets/kernel/qapplication.cpp:2898
#24 0x000000000094e7f5 in main(int, char**) (argc=1, argv=0x7fffffffd498) at /data/KDE/src/kde/kdemultimedia/kdenlive/src/main.cpp:163
Test Plan

kdenlive no longer crashes at start

Diff Detail

Repository
R158 Kdenlive
Lint
Automatic diff as part of commit; lint not applicable.
Unit
Automatic diff as part of commit; unit tests not applicable.
dvratil requested review of this revision.Mar 20 2018, 2:42 PM
dvratil created this revision.
dvratil added a reviewer: mardelle.
mardelle accepted this revision.Mar 23 2018, 6:38 AM

Thanks for that! That should fix the crash with the flatpak package on Nvidia, great!

This revision is now accepted and ready to land.Mar 23 2018, 6:38 AM
This revision was automatically updated to reflect the committed changes.