OpenBoard-org / OpenBoard

OpenBoard is a cross-platform interactive whiteboard application intended for use in a classroom setting.
https://openboard.ch/
GNU General Public License v3.0
2.36k stars 426 forks source link

OpenBoard 1.7.0 on Wayland: Segmentation fault when clicking into the "List of screens used for Control, Display and Previous pages" entry field #843

Open maehne opened 10 months ago

maehne commented 10 months ago

I installed OpenBoard 1.7.0 on an up-to-date Endeavour OS (based on Arch Linux, x86_64 processor platform) installation using the AUR PKGBUILD. The AUR package currently builds OpenBoard agains Qt 5.15.11. A segmentation fault happens every time, when clicking with the mouse into the "List of screens used for Control, Display and Previous pages" entry field of the Preferences window. The backtrace is:

Thread 1 "openboard" received signal SIGSEGV, Segmentation fault.
0x00007fffec8a051b in QMetaObject::cast (
    this=this@entry=0x7ffff56856a0 <QWidgetWindow::staticMetaObject>, 
    obj=obj@entry=0x555557259ab0) at kernel/qmetaobject.cpp:389
Downloading source file /usr/src/debug/qt5-base/qtbase/src/corelib/kernel/qmetaobject.cpp
389         return (obj && obj->metaObject()->inherits(this)) ? obj : nullptr;  
(gdb) bt
#0  0x00007fffec8a051b in QMetaObject::cast(QObject const*) const
    (this=this@entry=0x7ffff56856a0 <QWidgetWindow::staticMetaObject>, obj=obj@entry=0x555557259ab0) at kernel/qmetaobject.cpp:389
#1  0x00007fffec8a055a in QMetaObject::cast(QObject*) const
    (this=this@entry=0x7ffff56856a0 <QWidgetWindow::staticMetaObject>, obj=obj@entry=0x555557259ab0) at kernel/qmetaobject.cpp:378
#2  0x00007ffff5176302 in qobject_cast<QWidgetWindow*>(QObject*)
    (object=0x555557259ab0)
    at ../../include/QtCore/../../src/corelib/kernel/qobject.h:519
#3  QApplicationPrivate::notifyActiveWindowChange(QWindow*)
    (this=<optimized out>, previous=<optimized out>)
    at kernel/qapplication.cpp:2104
#4  0x00007fffecd4a555 in QGuiApplicationPrivate::processActivatedEvent(QWindowSystemInterfacePrivate::ActivatedWindowEvent*) (e=<optimized out>)
    at kernel/qguiapplication.cpp:2518
#5  0x00007fffecd2a6f5 in QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>) (flags=flags@entry=...)
    at kernel/qwindowsysteminterface.cpp:1169
#6  0x00007fffecd2a831 in QWindowSystemInterface::flushWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>) (flags=...)
    at kernel/qwindowsysteminterface.cpp:1138
#7  0x00007fffec8c3bd4 in QObject::event(QEvent*)
    (this=0x5555571ab270, e=0x55555710f910) at kernel/qobject.cpp:1347
#8  0x00007ffff51788ff in QApplicationPrivate::notify_helper(QObject*, QEvent*)
    (this=<optimized out>, receiver=0x5555571ab270, e=0x55555710f910)
    at kernel/qapplication.cpp:3640
#9  0x00007fffec89c168 in QCoreApplication::notifyInternal2(QObject*, QEvent*)
    (receiver=0x5555571ab270, event=0x55555710f910)
    at kernel/qcoreapplication.cpp:1064
#10 0x00007fffec8a10cb in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) (receiver=0x0, event_type=0, data=0x555555a9f810)
    at kernel/qcoreapplication.cpp:1821
#11 0x00007fffec8e7138 in postEventSourceDispatch(GSource*, GSourceFunc, gpointer) (s=0x555555ad1d20) at kernel/qeventdispatcher_glib.cpp:277
#12 0x00007fffeb331f69 in g_main_dispatch (context=0x7fffd0000ec0)
    at ../glib/glib/gmain.c:3476
#13 0x00007fffeb390367 in g_main_context_dispatch_unlocked
    (context=0x7fffd0000ec0) at ../glib/glib/gmain.c:4284
#14 g_main_context_iterate_unlocked.isra.0
    (context=context@entry=0x7fffd0000ec0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at ../glib/glib/gmain.c:4349
#15 0x00007fffeb330162 in g_main_context_iteration
    (context=0x7fffd0000ec0, may_block=1) at ../glib/glib/gmain.c:4414
#16 0x00007fffec8eaf7c in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) (this=0x555555a7e9c0, flags=...)
    at kernel/qeventdispatcher_glib.cpp:423
#17 0x00007fffec89ae74 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) (this=this@entry=0x7fffffffb8b0, flags=..., flags@entry=...)
    at ../../include/QtCore/../../src/corelib/global/qflags.h:69
#18 0x00007ffff537456b in QDialog::exec() (this=0x5555560f4ab0)
    at ../../include/QtCore/../../src/corelib/global/qflags.h:121
#19 0x00007fffec8d1253 in doActivate<false>(QObject*, int, void**)
    (sender=0x555555e903e0, signal_index=4, argv=0x7fffffffba00)
    at kernel/qobject.cpp:3937
#20 0x00007ffff516bbb7 in QAction::triggered(bool)
    (this=this@entry=0x555555e903e0, _t1=<optimized out>)
    at .moc/moc_qaction.cpp:376
#21 0x00007ffff517160b in QAction::activate(QAction::ActionEvent)
    (this=0x555555e903e0, event=<optimized out>) at kernel/qaction.cpp:1161
#22 0x00007ffff52f42db in QMenuPrivate::activateCausedStack(QVector<QPointer<QWidget> > const&, QAction*, QAction::ActionEvent, bool)
    (this=this@entry=0x555555e37310, causedStack=..., action=action@entry=0x555555e903e0, action_e=action_e@entry=QAction::Trigger, self=self@entry=true)
    at widgets/qmenu.cpp:1384
#23 0x00007ffff52f43fd in QMenuPrivate::activateAction(QAction*, QAction::ActionEvent, bool)
    (this=0x555555e37310, action=0x555555e903e0, action_e=QAction::Trigger, self=true) at widgets/qmenu.cpp:1461
#24 0x00007ffff51af1a1 in QWidget::event(QEvent*)
    (this=0x555556385f50, event=0x7fffffffc000) at kernel/qwidget.cpp:8671
#25 0x00007ffff51788ff in QApplicationPrivate::notify_helper(QObject*, QEvent*)
    (this=this@entry=0x555555a9f6a0, receiver=receiver@entry=0x555556385f50, e=e@entry=0x7fffffffc000) at kernel/qapplication.cpp:3640
#26 0x00007ffff517ddaf in QApplication::notify(QObject*, QEvent*)
    (this=<optimized out>, receiver=0x555556385f50, e=0x7fffffffc000)
    at kernel/qapplication.cpp:3084
#27 0x00007fffec89c168 in QCoreApplication::notifyInternal2(QObject*, QEvent*)
    (receiver=0x555556385f50, event=0x7fffffffc000)
    at kernel/qcoreapplication.cpp:1064
--Type <RET> for more, q to quit, c to continue without paging--
#28 0x00007fffec89c1f3 in QCoreApplication::sendSpontaneousEvent(QObject*, QEvent*) (receiver=<optimized out>, event=<optimized out>)
    at kernel/qcoreapplication.cpp:1474
#29 0x00007ffff517c0ea in QApplicationPrivate::sendMouseEvent(QWidget*, QMouseEvent*, QWidget*, QWidget*, QWidget**, QPointer<QWidget>&, bool, bool)
    (receiver=0x555556385f50, event=0x7fffffffc000, alienWidget=<optimized out>, nativeWidget=0x555556385f50, buttonDown=<optimized out>, lastMouseReceiver=..., spontaneous=true, onlyDispatchEnterLeave=false)
    at kernel/qapplication.cpp:2622
#30 0x00007ffff51cd9b4 in QWidgetWindow::handleMouseEvent(QMouseEvent*)
    (this=this@entry=0x555557197420, event=event@entry=0x7fffffffc360)
    at kernel/qwidgetwindow.cpp:580
#31 0x00007ffff51cec07 in QWidgetWindow::event(QEvent*)
    (this=0x555557197420, event=0x7fffffffc360) at kernel/qwidgetwindow.cpp:300
#32 0x00007ffff51788ff in QApplicationPrivate::notify_helper(QObject*, QEvent*)
    (this=<optimized out>, receiver=0x555557197420, e=0x7fffffffc360)
    at kernel/qapplication.cpp:3640
#33 0x00007fffec89c168 in QCoreApplication::notifyInternal2(QObject*, QEvent*)
    (receiver=0x555557197420, event=0x7fffffffc360)
    at kernel/qcoreapplication.cpp:1064
#34 0x00007fffec89c1f3 in QCoreApplication::sendSpontaneousEvent(QObject*, QEvent*) (receiver=<optimized out>, event=<optimized out>)
    at kernel/qcoreapplication.cpp:1474
#35 0x00007fffecd4196c in QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent*) (e=0x5555571a7f00)
    at kernel/qguiapplication.cpp:2285
#36 0x00007fffecd2a6f5 in QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>) (flags=...)
    at kernel/qwindowsysteminterface.cpp:1169
#37 0x00007fffd7d21ce5 in userEventSourceDispatch(_GSource*, int (*)(void*), void*) () at /usr/lib/libQt5WaylandClient.so.5
#38 0x00007fffeb331f69 in g_main_dispatch (context=0x7fffd0000ec0)
    at ../glib/glib/gmain.c:3476
#39 0x00007fffeb390367 in g_main_context_dispatch_unlocked
    (context=0x7fffd0000ec0) at ../glib/glib/gmain.c:4284
#40 g_main_context_iterate_unlocked.isra.0
    (context=context@entry=0x7fffd0000ec0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at ../glib/glib/gmain.c:4349
#41 0x00007fffeb330162 in g_main_context_iteration
    (context=0x7fffd0000ec0, may_block=1) at ../glib/glib/gmain.c:4414
#42 0x00007fffec8eaf7c in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) (this=0x555555a7e9c0, flags=...)
    at kernel/qeventdispatcher_glib.cpp:423
#43 0x00007fffec89ae74 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) (this=this@entry=0x7fffffffc710, flags=..., flags@entry=...)
    at ../../include/QtCore/../../src/corelib/global/qflags.h:69
#44 0x00007ffff52fbb88 in QMenuPrivate::exec(QPoint const&, QAction*, std::function<QPoint (QSize const&)>)
    (this=0x555555e37310, p=..., action=0x0, positionFunction=...)
    at ../../include/QtCore/../../src/corelib/global/qflags.h:121
#45 0x00007ffff535c16d in QToolButtonPrivate::popupTimerDone()
    (this=0x555555f3d210) at widgets/qtoolbutton.cpp:809
#46 0x00007fffec8d1253 in doActivate<false>(QObject*, int, void**)
    (sender=0x555555f3c7d0, signal_index=7, argv=0x7fffffffc8d0)
    at kernel/qobject.cpp:3937
#47 0x00007ffff525f01d in QAbstractButtonPrivate::emitPressed()
    (this=0x555555f3d210) at widgets/qabstractbutton.cpp:438
#48 0x00007ffff525f227 in QAbstractButton::mousePressEvent(QMouseEvent*)
    (this=0x555555f3c7d0, e=0x7fffffffcf20) at widgets/qabstractbutton.cpp:1017
#49 0x00007ffff535c5ad in QToolButton::mousePressEvent(QMouseEvent*)
    (this=0x555555f3c7d0, e=0x7fffffffcf20) at widgets/qtoolbutton.cpp:613
#50 0x00007ffff51af4e9 in QWidget::event(QEvent*)
    (this=0x555555f3c7d0, event=0x7fffffffcf20) at kernel/qwidget.cpp:8667
#51 0x00007ffff51788ff in QApplicationPrivate::notify_helper(QObject*, QEvent*)
    (this=this@entry=0x555555a9f6a0, receiver=receiver@entry=0x555555f3c7d0, e=e@entry=0x7fffffffcf20) at kernel/qapplication.cpp:3640
#52 0x00007ffff517ddaf in QApplication::notify(QObject*, QEvent*)
    (this=<optimized out>, receiver=0x555555f3c7d0, e=0x7fffffffcf20)
    at kernel/qapplication.cpp:3084
#53 0x00007fffec89c168 in QCoreApplication::notifyInternal2(QObject*, QEvent*)
    (receiver=0x555555f3c7d0, event=0x7fffffffcf20)
    at kernel/qcoreapplication.cpp:1064
#54 0x00007fffec89c1f3 in QCoreApplication::sendSpontaneousEvent(QObject*, QEvent*) (receiver=<optimized out>, event=<optimized out>)
    at kernel/qcoreapplication.cpp:1474
#55 0x00007ffff517c0ea in QApplicationPrivate::sendMouseEvent(QWidget*, QMouseEvent*, QWidget*, QWidget*, QWidget**, QPointer<QWidget>&, bool, bool)
    (receiver=0x555555f3c7d0, event=0x7fffffffcf20, alienWidget=<optimized out>, nativeWidget=0x555555aeda40, buttonDown=<optimized out>, lastMouseReceiver=...,--Type <RET> for more, q to quit, c to continue without paging--
 spontaneous=true, onlyDispatchEnterLeave=false)
    at kernel/qapplication.cpp:2622
#56 0x00007ffff51cceb5 in QWidgetWindow::handleMouseEvent(QMouseEvent*)
    (this=this@entry=0x555556079080, event=event@entry=0x7fffffffd280)
    at kernel/qwidgetwindow.cpp:684
#57 0x00007ffff51cec07 in QWidgetWindow::event(QEvent*)
    (this=0x555556079080, event=0x7fffffffd280) at kernel/qwidgetwindow.cpp:300
#58 0x00007ffff51788ff in QApplicationPrivate::notify_helper(QObject*, QEvent*)
    (this=<optimized out>, receiver=0x555556079080, e=0x7fffffffd280)
    at kernel/qapplication.cpp:3640
#59 0x00007fffec89c168 in QCoreApplication::notifyInternal2(QObject*, QEvent*)
    (receiver=0x555556079080, event=0x7fffffffd280)
    at kernel/qcoreapplication.cpp:1064
#60 0x00007fffec89c1f3 in QCoreApplication::sendSpontaneousEvent(QObject*, QEvent*) (receiver=<optimized out>, event=<optimized out>)
    at kernel/qcoreapplication.cpp:1474
#61 0x00007fffecd4196c in QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent*) (e=0x7fffc8001350)
    at kernel/qguiapplication.cpp:2285
#62 0x00007fffecd2a6f5 in QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>) (flags=...)
    at kernel/qwindowsysteminterface.cpp:1169
#63 0x00007fffd7d21ce5 in userEventSourceDispatch(_GSource*, int (*)(void*), void*) () at /usr/lib/libQt5WaylandClient.so.5
#64 0x00007fffeb331f69 in g_main_dispatch (context=0x7fffd0000ec0)
    at ../glib/glib/gmain.c:3476
#65 0x00007fffeb390367 in g_main_context_dispatch_unlocked
    (context=0x7fffd0000ec0) at ../glib/glib/gmain.c:4284
#66 g_main_context_iterate_unlocked.isra.0
    (context=context@entry=0x7fffd0000ec0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at ../glib/glib/gmain.c:4349
#67 0x00007fffeb330162 in g_main_context_iteration
    (context=0x7fffd0000ec0, may_block=1) at ../glib/glib/gmain.c:4414
#68 0x00007fffec8eaf7c in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) (this=0x555555a7e9c0, flags=...)
    at kernel/qeventdispatcher_glib.cpp:423
#69 0x00007fffec89ae74 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) (this=this@entry=0x7fffffffd620, flags=..., flags@entry=...)
    at ../../include/QtCore/../../src/corelib/global/qflags.h:69
#70 0x00007fffec89c313 in QCoreApplication::exec() ()
    at ../../include/QtCore/../../src/corelib/global/qflags.h:121
#71 0x00005555556267e7 in main ()

The crash does not happen when running in an X11 session or using QT_QPA_PLATFORM=xcb openboard to force using the X11 compatibility layer on Wayland. I was also not able to observe the crash on Windows or macOS.

As a side note: There are other Wayland-related issues as well, e.g.:

letsfindaway commented 10 months ago

See #617. Indeed, QT_QPA_PLATFORM=xcb helps to avoid this problem.

But as you already found out, many other problems remain when using Wayland, especially because screenshots cannot be taken under Wayland the same way as with X11. See e.g. #665 and #679.

Also controlling the exact window position is not possible under Wayland. Read e.g. https://gitlab.gnome.org/GNOME/mutter/-/issues/316.

So for the time being I would advise against using OpenBoard under Wayland.

maehne commented 10 months ago

Thanks for the feedback! I am well aware of Wayland's restrictions and its impact on tools I am using daily for my teaching (e.g., also Projecteur is only partially usable). However, reporting the observed issues is the first step for fixing them - even if it takes considerable time. I hesitated long to make the switch to Wayland, but I have to say that it nowadays gives me the smoother user experience - especially when moving between many different classrooms and work places (all having different monitor setups). Even screen sharing/screen casting nowadays works well due to xdg-desktop-portal. So the biggest problems remain with presentation tools requiring to impose exact window positions. I would love to see these issues sorted out. However, some problems seem to require a coordinated effort by teams taking care of the different parts of the involved library/tool stack.

letsfindaway commented 10 months ago

So the biggest problems remain with presentation tools requiring to impose exact window positions. I would love to see these issues sorted out.

It seems that using Xwayland by setting

GDK_BACKEND=x11

will mitigate the window positioning problem. At least in my short tests OpenBoard run fine on a multi-monitor setup, except for the screenshot problem.

So

QT_QPA_PLATFORM=xcb  # select the QXcbIntegrationPlugin for X Window System (X11) support
GDK_BACKEND=x11      # force application to use Xwayland

would currently be my recommendation.

maehne commented 10 months ago

Thanks for the recommendation! For my understanding, could you please explain why also GDK_BACKEND=x11 is needed, OpenBoard itself is based on Qt? In my testing setting only QT_QPA_PLATFORM=xcb was sufficient, but I have to admit that I tested only basic functionalities.

letsfindaway commented 10 months ago

Originally I thought I need this for correct positioning of windows. But when I test it now, QT_QPA_PLATFORM=xcb is sufficient.

maehne commented 5 months ago

The segmentation fault still occurs in OpenBoard 1.7.1. The workaround QT_QPA_PLATFORM=xcb still helps.

maehne commented 5 months ago

@letsfindaway: What do you think of adding the workaround to the desktop file?

diff --unified --recursive --text OpenBoard-1.7.1/resources/linux/ch.openboard.OpenBoard.desktop OpenBoard-1.7.1.new/resources/linux/ch.openboard.OpenBoard.desktop
--- OpenBoard-1.7.1/resources/linux/ch.openboard.OpenBoard.desktop      2024-05-10 13:17:07.104142963 +0200
+++ OpenBoard-1.7.1.new/resources/linux/ch.openboard.OpenBoard.desktop  2024-05-10 13:17:40.960655024 +0200
@@ -2,7 +2,7 @@
 Encoding=UTF-8
 Name=OpenBoard
 Comment=OpenBoard, an interactive white board application
-Exec=openboard %f
+Exec=QT_QPA_PLATFORM=xcb openboard %f
 Icon=ch.openboard.OpenBoard
 StartupNotify=true
 Terminal=false

I successfully tested this in KDE Plasma 6 Wayland and X11 sessions on Arch Linux.

maehne commented 4 months ago

Over the past weeks, I observed some drawbacks when using QT_QPA_PLATFORM=xcb openboard in a KDE Plasma session:

I have not observed these issues when using the windowed mode without active Multi Screen and running OpenBoard natively under Wayland (QT_QPA_PLATFORM=wayland, which is the default if not set explicitly). Of course, the segfault still persists when trying to edit the screen list with OpenBoard 1.7.1 build on an up-to-date Arch Linux with kernel version 6.9.3, KDE Plasma 6.05, Qt 6.7.1. But otherwise, OpenBoard seems to behave more sane. I can even switch to the Desktop and draw on it. Due to the windowed mode, I can move OpenBoard with KDE Plasma's keyboard shortcut around to different screens and even switch it to full screen mode.