With https://cgit.freedesktop.org/xorg/xserver/commit/hw/xwayland?id=ca17f3e9fd3b59fdc5ffd0e5d78e4db6ddc87aa1 Xwayland gained the functionality to lock a pointer if it is confined + hidden. This is processed by KWin in two consecutive PointerInputRedirection::enablePointerConstraints() calls. One application using this is Neverball in Xwayland mode. When I remove one of the two OSD::show(...) calls in PointerInputRedirection::enablePointerConstraints() it works fine. Otherwise the whole session hangs and can't be used any more. SIGKILL to KWin is necessary. The creation of the OSD also seems to leak memory in general, since the OnScreenNotification object isn't destroyed after it becomes hidden again.
So the main point here is that we get both confined and locked?
We get confined and locked probably at the same time, but we setConfined first in https://cgit.kde.org/kwin.git/tree/pointer_input.cpp#n599, show the confined OSD and return on https://cgit.kde.org/kwin.git/tree/pointer_input.cpp#n626 Then on the next call to PointerInputRedirection::update(), which again calls PointerInputRedirection::enablePointerConstraints(), we go into https://cgit.kde.org/kwin.git/tree/pointer_input.cpp#n638 and show the other OSD. The thing is though when one of the two OSD::show(..) calls get removed, the code works without problems, so there seems to be no general problem with confining and locking at the same time.
I'm not sure whether we actually support locking and confining at the same time, but yeah that's not the problem. It looks like the OSD just doesn't support being shown multiple times. Or in general that our internal windows don't handle getting shown multiple times.
Looking at the code everything seems fine. The OSD is only created on very first show (it's a static instance, so no leak). So the problem might be the change of the Qml prior to actual showing.
You're sure it's created only once? While s_osd is a static OnScreenNotification pointer, we still always call create() in osd() and in create() a new OnScreenNotification instance is created with its address being set as the new value of the static pointer s_osd.
It's a static initialization: it's only evaluated the first time it's executed
See http://en.cppreference.com/w/cpp/language/storage_duration Section "Static local variables"
I just created a test case for the situation and this results in: wl_surface@13: error 1: Surface already constrained It looks to me like what XWayland does is not valid on Wayland. And I just checked with the spec (https://cgit.freedesktop.org/wayland/wayland-protocols/tree/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml): " For any surface, only one lock or confinement may be active across all wl_pointer objects of the same seat. If a lock or confinement is requested when another lock or confinement is active or requested on the same surface and with any of the wl_pointer objects of the same seat, an 'already_constrained' error will be raised." The problem might now be that XWayland gets a protocol error that causes the hang in KWin as XWayland goes down. I think the change in XWayland should be reverted or fixed ASAP!
Created attachment 107391 [details] Patch to autotest For reference the patch added to the auto test
Thanks for digging into this. You're right that the cursor can't be locked and confined at the same time. The Xwayland code works like this: First confine. If then a certain condition is met (cursor hidden) release the confinement and directly afterwards lock instead. Then showing the lock notice instead of the confine notice somehow kills KWin.
OK, I'll try to adjust the test case for this condition.
I'm not able to reproduce the problem, could you please add an output of WAYLAND_DEBUG, so that I can get the actual sequence of commands? Unrelated found a crash in another test case: Thread 1 "testPointerCons" received signal SIGSEGV, Segmentation fault. 0x00007f33637ca3be in KWin::QPA::Window::unmap (this=0x5555560d99c0) at /home/martin/src/kf5/kde/workspace/kwin/plugins/qpa/window.cpp:113 113 m_shellClient->setInternalFramebufferObject(QSharedPointer<QOpenGLFramebufferObject>()); (gdb) bt #0 0x00007f33637ca3be in KWin::QPA::Window::unmap() (this=0x5555560d99c0) at /home/martin/src/kf5/kde/workspace/kwin/plugins/qpa/window.cpp:113 #1 0x00007f33637c9fd0 in KWin::QPA::Window::setVisible(bool) (this=0x5555560d99c0, visible=false) at /home/martin/src/kf5/kde/workspace/kwin/plugins/qpa/window.cpp:76 #2 0x00007f33744f7dac in QWindow::setVisible(bool) () at /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5 #3 0x00007f3344867b66 in PlasmaQuick::Dialog::setVisible(bool) (this=0x55555603a160, visible=false) at /home/martin/src/kf5/frameworks/plasma-framework/src/plasmaquick/dialog.cpp:1379 #4 0x00007f3344868476 in PlasmaQuick::Dialog::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) (_o=0x55555603a160, _c=QMetaObject::WriteProperty, _id=9, _a=0x7fffffffa7f0) at /opt/build/kf5/frameworks/plasma-framework/src/plasmaquick/KF5PlasmaQuick_autogen/include/moc_dialog.cpp:346 #5 0x00007f334486861d in PlasmaQuick::Dialog::qt_metacall(QMetaObject::Call, int, void**) (this=0x55555603a160, _c=QMetaObject::WriteProperty, _id=9, _a=0x7fffffffa7f0) at /opt/build/kf5/frameworks/plasma-framework/src/plasmaquick/KF5PlasmaQuick_autogen/include/moc_dialog.cpp:399 #6 0x00007f337aaaef52 in QQmlPropertyPrivate::write(QObject*, QQmlPropertyData const&, QVariant const&, QQmlContextData*, QFlags<QQmlPropertyPrivate::WriteFlag>) (object=object@entry=0x55555603a160, property=..., value=..., context=context@entry=0x5555561d1fa0, flags=...) at qml/qqmlproperty.cpp:1259 #7 0x00007f337aab0693 in QQmlPropertyPrivate::writeValueProperty(QObject*, QQmlPropertyData const&, QVariant const&, QQmlContextData*, QFlags<QQmlPropertyPrivate::WriteFlag>) (object=0x55555603a160, core=..., value=..., context=0x5555561d1fa0, flags=...) at qml/qqmlproperty.cpp:1183 #8 0x00007f337ab1cef5 in QQmlBinding::write(QQmlPropertyData const&, QV4::Value const&, bool, QFlags<QQmlPropertyPrivate::WriteFlag>) (this=this@entry=0x5555561174c0, core=..., result=..., isUndefined=<optimized out>, flags=...) at qml/qqmlbinding.cpp:333 #9 0x00007f337ab1df67 in QQmlBinding::update(QFlags<QQmlPropertyPrivate::WriteFlag>) (this=0x5555561174c0, flags=...) at qml/qqmlbinding.cpp:197 #10 0x00007f337ab1e9ce in QQmlBinding::refresh() (this=<optimized out>) at qml/qqmlbinding.cpp:409 #11 0x00007f337aaf3934 in QQmlNotifier::emitNotify(QQmlNotifierEndpoint*, void**) (endpoint=<optimized out>, a=a@entry=0x0) at qml/qqmlnotifier.cpp:100 #12 0x00007f337aa9e61c in QQmlData::signalEmitted(QAbstractDeclarativeData*, QObject*, int, void**) (object=0x555555ef7de0, index=3, a=0x0) at qml/qqmlengine.cpp:779 #13 0x00007f3373cb2524 in QMetaObject::activate(QObject*, int, int, void**) (sender=0x555555ef7de0, signalOffset=<optimized out>, local_signal_index=<optimized out>, argv=0x0) at kernel/qobject.cpp:3618 #14 0x00007f337c580e2b in KWin::OnScreenNotification::visibleChanged() (this=0x555555ef7de0) at /opt/build/kf5/kde/workspace/kwin/kwin_autogen/EWIEGA46WW/moc_onscreennotification.cpp:220 #15 0x00007f337c4bbd8b in KWin::OnScreenNotification::setVisible(bool) (this=0x555555ef7de0, visible=false) at /home/martin/src/kf5/kde/workspace/kwin/onscreennotification.cpp:115 #16 0x00007f337c4bd205 in std::__invoke_impl<void, void (KWin::OnScreenNotification::*&)(bool), KWin::OnScreenNotification*&, bool&>(std::__invoke_memfun_deref, void (KWin::OnScreenNotification::*&)(bool), KWin::OnScreenNotification*&, bool&) (__f=@0x555555ef69e0: (void (KWin::OnScreenNotification::*)(KWin::OnScreenNotification * const, bool)) 0x7f337c4bbd56 <KWin::OnScreenNotification::setVisible(bool)>, __t=@0x555555ef69f8: 0x555555ef7de0, __args#0=@0x555555ef69f0: false) at /usr/include/c++/7/bits/invoke.h:73 #17 0x00007f337c4bd13f in std::__invoke<void (KWin::OnScreenNotification::*&)(bool), KWin::OnScreenNotification*&, bool&>(void (KWin::OnScreenNotification::*&)(bool), KWin::OnScreenNotification*&, bool&) (__fn= @0x555555ef69e0: (void (KWin::OnScreenNotification::*)(KWin::OnScreenNotification * const, bool)) 0x7f337c4bbd56 <KWin::OnScreenNotification::setVisible(bool)>, __args#0=@0x555555ef69f8: 0x555555ef7de0, __args#1=@0x555555ef69f0: false) at /usr/include/c++/7/bits/invoke.h:95 #18 0x00007f337c4bd04b in std::_Bind<void (KWin::OnScreenNotification::*(KWin::OnScreenNotification*, bool))(bool)>::__call<void, QTimer::QPrivateSignal&, 0ul, 1ul>(std::tuple<QTimer::QPrivateSignal&>&&, std::_Index_tuple<0ul, 1ul>) (this=0x555555ef69e0, __args=<unknown type in /opt/build/kf5/kde/workspace/kwin/libkwin.so.5, CU 0x1297de2, DIE 0x12cc6b2>) at /usr/include/c++/7/functional:467 #19 0x00007f337c4bcfcb in std::_Bind<void (KWin::OnScreenNotification::*(KWin::OnScreenNotification*, bool))(bool)>::operator()<QTimer::QPrivateSignal&, void>(QTimer::QPrivateSignal&) (this=0x555555ef69e0, __args#0=...) at /usr/include/c++/7/functional:551 #20 0x00007f337c4bcec2 in QtPrivate::FunctorCall<QtPrivate::IndexesList<0>, QtPrivate::List<QTimer::QPrivateSignal>, void, std::_Bind<void (KWin::OnScreenNotification::*(KWin::OnScreenNotification*, bool))(bool)> >::call(std::_Bind<void (KWin::OnScreenNotification::*(KWin::OnScreenNotification*, bool))(bool)>&, void**) (f=..., arg=0x7fffffffc820) at /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs_impl.h:135 #21 0x00007f337c4bce60 in QtPrivate::Functor<std::_Bind<void (KWin::OnScreenNotification::*(KWin::OnScreenNotification*, bool))(bool)>, 1>::call<QtPrivate::List<QTimer::QPrivateSignal>, void>(std::_Bind<void (KWin::OnScreenNotification::*(KWin::OnScreenNotification*, bool))(bool)>&, void*, void**) (f=..., arg=0x7fffffffc820) at /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs_impl.h:192 #22 0x00007f337c4bcdcd in QtPrivate::QFunctorSlotObject<std::_Bind<void (KWin::OnScreenNotification::*(KWin::OnScreenNotification*, bool))(bool)>, 1, QtPrivate::List<QTimer::QPrivateSignal>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) (which=1, this_=0x555555ef69d0, r=0x555555ef7de0, a=0x7fffffffc820, ret=0x0) at /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject_impl.h:169 #23 0x00007f3373cb21ae in QtPrivate::QSlotObjectBase::call(QObject*, void**) (a=0x7fffffffc820, r=0x555555ef7de0, this=<optimized out>) at ../../include/QtCore/../../src/corelib/kernel/qobject_impl.h:101 #24 0x00007f3373cb21ae in QMetaObject::activate(QObject*, int, int, void**) (sender=sender@entry=0x555555f24870, signalOffset=<optimized out>, local_signal_index=local_signal_index@entry=0, argv=argv@entry=0x0) at kernel/qobject.cpp:3723 #25 0x00007f3373cb2737 in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) (sender=sender@entry=0x555555f24870, m=m@entry=0x7f3373ed0760 <QTimer::staticMetaObject>, local_signal_index=local_signal_index@entry=0, argv=argv@entry=0x0) at kernel/qobject.cpp:3602 #26 0x00007f3373d2b780 in QTimer::timeout(QTimer::QPrivateSignal) (this=this@entry=0x555555f24870) at .moc/moc_qtimer.cpp:198 ---Type <return> to continue, or q <return> to quit--- #27 0x00007f3373cbe5f8 in QTimer::timerEvent(QTimerEvent*) (this=0x555555f24870, e=<optimized out>) at kernel/qtimer.cpp:254 #28 0x00007f3373cb2bfb in QObject::event(QEvent*) (this=0x555555f24870, e=<optimized out>) at kernel/qobject.cpp:1285 #29 0x00007f3374a89bec in QApplicationPrivate::notify_helper(QObject*, QEvent*) () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5 #30 0x00007f3374a91381 in QApplication::notify(QObject*, QEvent*) () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5 #31 0x00007f3373c86850 in QCoreApplication::notifyInternal2(QObject*, QEvent*) (receiver=0x555555f24870, event=event@entry=0x7fffffffcb50) at kernel/qcoreapplication.cpp:988 #32 0x00007f3373cd935e in QCoreApplication::sendEvent(QObject*, QEvent*) (event=0x7fffffffcb50, receiver=<optimized out>) at ../../include/QtCore/../../src/corelib/kernel/qcoreapplication.h:231 #33 0x00007f3373cd935e in QTimerInfoList::activateTimers() (this=this@entry=0x5555557eace0) at kernel/qtimerinfo_unix.cpp:644 #34 0x00007f3373cd605c in QEventDispatcherUNIXPrivate::activateTimers() (this=this@entry=0x5555557eac40) at kernel/qeventdispatcher_unix.cpp:249 #35 0x00007f3373cd726a in QEventDispatcherUNIX::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) (this=<optimized out>, flags=...) at kernel/qeventdispatcher_unix.cpp:514 #36 0x00007f33637cb4cd in QUnixEventDispatcherQPA::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () at /opt/build/kf5/kde/workspace/kwin/plugins/qpa/KWinQpaPlugin.so #37 0x00007f3373c8483a in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) (this=0x7fffffffcd30, flags=...) at kernel/qeventloop.cpp:212 #38 0x000055555556a913 in QTestEventLoop::enterLoopMSecs(int) (this=0x7fffffffce78, ms=5000) at /usr/include/x86_64-linux-gnu/qt5/QtTest/qtesteventloop.h:105 #39 0x000055555556abc0 in QSignalSpy::wait(int) (this=0x7fffffffce50, timeout=5000) at /usr/include/x86_64-linux-gnu/qt5/QtTest/qsignalspy.h:149 #40 0x0000555555565f74 in TestPointerConstraints::testConfinedPointer() (this=0x7fffffffdd20) at /home/martin/src/kf5/kde/workspace/kwin/autotests/integration/pointer_constraints_test.cpp:217 #41 0x00005555555694f1 in TestPointerConstraints::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) (_o=0x7fffffffdd20, _c=QMetaObject::InvokeMetaMethod, _id=4, _a=0x7fffffffd420) at /opt/build/kf5/kde/workspace/kwin/autotests/integration/testPointerConstraints_autogen/include/pointer_constraints_test.moc:116 #42 0x00007f3373c94b4e in QMetaMethod::invoke(QObject*, Qt::ConnectionType, QGenericReturnArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument) const (this=<optimized out>, object=0x7fffffffdd20, connectionType=Qt::DirectConnection, returnValue=..., val0=..., val1=..., val2=..., val3=..., val4=..., val5=..., val6=..., val7=..., val8=..., val9=...) at kernel/qmetaobject.cpp:2222 #43 0x00007f337ca9c707 in () at /usr/lib/x86_64-linux-gnu/libQt5Test.so.5 #44 0x00007f337ca9d0f6 in () at /usr/lib/x86_64-linux-gnu/libQt5Test.so.5 #45 0x00007f337ca9d732 in () at /usr/lib/x86_64-linux-gnu/libQt5Test.so.5 #46 0x00007f337ca9dc49 in QTest::qExec(QObject*, int, char**) () at /usr/lib/x86_64-linux-gnu/libQt5Test.so.5 #47 0x0000555555569422 in main(int, char**) (argc=1, argv=0x7fffffffdea8) at /home/martin/src/kf5/kde/workspace/kwin/autotests/integration/pointer_constraints_test.cpp:472
Could you please check whether the freeze matches #384441 ?
I just tried and the problem is still there. KWin log with WAYLAND_DEBUG=server: [2240489,397] wl_surface@20.attach(wl_buffer@11, 0, 0) [2240489,410] wl_surface@20.damage(0, 0, 3840, 2160) [2240489,425] wl_surface@20.frame(new id wl_callback@19) [2240489,432] wl_surface@20.commit() [2240505,902] -> wl_buffer@11.release() [2240506,079] -> wl_callback@19.done(1020125252) [2240506,089] -> wl_display@1.delete_id(19) [2240506,120] wl_surface@20.attach(wl_buffer@11, 0, 0) [2240506,133] wl_surface@20.damage(0, 0, 3840, 2160) [2240506,141] wl_surface@20.frame(new id wl_callback@19) [2240506,150] wl_surface@20.commit() [2240515,906] -> wl_pointer@15.button(64, 19836925, 272, 1) [2240516,972] zwp_pointer_constraints_v1@13.confine_pointer(new id zwp_confined_pointer_v1@21, wl_surface@20, wl_pointer@15, nil, 2) [2240517,053] -> zwp_confined_pointer_v1@21.confined() [2240531,221] wl_shm@6.create_pool(new id wl_shm_pool@22, fd 98, 4) [2240531,246] wl_shm_pool@22.create_buffer(new id wl_buffer@23, 0, 1, 1, 4, 0) [2240531,260] wl_shm_pool@22.destroy() [2240531,264] -> wl_display@1.delete_id(22) [2240531,267] zwp_confined_pointer_v1@21.destroy() [2240531,296] -> wl_display@1.delete_id(21) [2240531,300] zwp_pointer_constraints_v1@13.lock_pointer(new id zwp_locked_pointer_v1@24, wl_surface@20, wl_pointer@15, nil, 2) [2240531,345] -> zwp_locked_pointer_v1@24.locked()
I guess I need to compile the latest XWayland... the output looks exactly like what I had in my test case. As it's a freeze, I'm raising to critical.
You can use my script for compiling (change the rootdir and INST vars to your liking, an install in /usr/local though makes KWin directly using the compiled Xwayland on next launch): #!/bin/sh # setup environment for local install: rootdir=$HOME/Entwicklung/linux/xorg BLD=$rootdir/build-xwayland_only #export INST=$rootdir/install #export INST=/opt/xorg export INST=/usr/local export LD_LIBRARY_PATH=$INST/lib export PKG_CONFIG_PATH=$INST/lib/pkgconfig/:$INST/share/pkgconfig/ export PATH=$INST/bin:$PATH export ACLOCAL_PATH=$INST/share/aclocal export ACLOCAL="aclocal -I $ACLOCAL_PATH" mkdir -p src mkdir -p $BLD mkdir -p $INST mkdir -p $INST/var/log mkdir -p $ACLOCAL_PATH export MAKEFLAGS="j5" # run 5 threads, or use your own flags cd $rootdir/src # * These three are not necessary with the --disable-documentation flag, and # pull 1,400 MB of packages: # configure: error: Documentation build requested but doxygen not found. # Install doxygen or disable the documentation using --disable-documentation # configure: error: Documentation build requested but xmlto not found. # Install xmlto or disable the documentation using --disable-documentation # configure: error: Documentation build requested but graphviz's dot not found. # Install graphviz or disable the documentation using --disable-documentation git clone git://anongit.freedesktop.org/wayland/wayland cd wayland git pull cd $BLD mkdir wayland cd wayland ./../../src/wayland/autogen.sh --prefix=$INST # --disable-documentation make check make && make install cd $rootdir/src # wayland-protocols: git clone git://anongit.freedesktop.org/wayland/wayland-protocols cd wayland-protocols git pull cd $BLD mkdir wayland-protocols cd wayland-protocols ./../../src/wayland-protocols/autogen.sh --prefix=$INST make check make && make install cd $rootdir/src #git clone git://anongit.freedesktop.org/wayland/libinput #cd libinput #git pull #cd $BLD #mkdir libinput #cd $rootdir/src/libinput #meson --prefix=$INST $BLD/libinput #ninja -C $BLD/libinput #sudo ninja -C $BLD/libinput install #sudo udevadm hwdb --update #cd $rootdir/src # No package 'xfont2' found git clone git://anongit.freedesktop.org/xorg/lib/libXfont cd libXfont git pull cd $BLD mkdir libXfont cd libXfont ./../../src/libXfont/autogen.sh --prefix=$INST make check make && make install cd $rootdir/src git clone git://anongit.freedesktop.org/xorg/xserver cd xserver #git pull cd $BLD mkdir xserver cd xserver ./../../src/xserver/autogen.sh --prefix=$INST --disable-docs --disable-devel-docs \ --enable-xwayland --disable-xorg --disable-xvfb --disable-xnest \ --disable-xquartz --disable-xwin make check make && make install cd $rootdir/src # Links needed so XWayland works: mkdir -p $INST/share/X11/xkb/rules ln -s /usr/share/X11/xkb/rules/evdev $INST/share/X11/xkb/rules/ ln -s /usr/bin/xkbcomp $INST/bin/ # git clone git://anongit.freedesktop.org/wayland/weston # cd weston # git pull # cd $BLD # mkdir weston # cd weston # ./../../src/weston/autogen.sh --prefix=$INST --disable-setuid-install --with-xserver-path=$INST/bin/Xwayland # make check # runs Xwayland # make && make install # cd $rootdir/src # Weston configuration: mkdir -p ~/.config #cp weston/weston.ini.in ~/.config/weston.ini #editor ~/.config/weston.ini # edit to set background and turn on xwayland.so module
(based on https://wayland.freedesktop.org/ubuntu16.04.html)
With https://cgit.kde.org/kwin.git/commit/?id=6072b0cd6c370749f28418f22a1284de5aba3462 the OSDs have been removed. Therefore no freeze would be possible any longer.