- 
    
Bug
 - 
    Resolution: Done
 - 
    
P1: Critical
 - 
    5.12.5, 5.13.2
 - 
    None
 
- 
        
 - 
        93058de8d7e7c2f320c22b3bd898aa06cf5babcd (qt/qtwayland/dev)
 - 
        Wayland Project - Backlog task
 
QWaylandWindow::handleUpdate could create thousands of pending frame callbacks, causing compositor to terminate client connection. Reproducible with gnome, weston, sway and possibly other wlroots-based compositors.
See swaywm/sway#4506 for original report and wayland debug logs.
Conditions:
- Compositor does not process frame callbacks for off-screen applications. Instead, it fires and deletes all the callbacks once the app is visible again. This seems to be matching the expected behavior from wayland protocol spec, so I can't say that sway is in the wrong.
 - Application forces updates while off-screen and a certain code path (which I wasn't able to figure out) ends up in a call of QWaylandWindow::handleUpdate outside of frame callback. About every 10ms, if I'm reading the log from WAYLAND_DEBUG=client correctly.
 - Every time it's invoked, QWaylandWindow::handleUpdate attempts to destroy a pending wl_callback and schedule a new one. As explained in 1, even if the callback is destroyed on client side, it still remains pending in a compositor.
 - Once a certain critical mass of pending callbacks has been reached and the app regains focus, compositor starts firing and deleting all pending callbacks at once. Apparently this causes overflow of a fixed-size wayland connection buffer and termination of a client.
 
KWin avoids this crash by processing damage buffers and frame callbacks even for offscreen apps, which by itself is questionable.
Steps to reproduce:
- Start "GNOME (Wayland)" session (also reproducible with: Sway, Weston).
 - Compile Qt5 example application from qt5/examples/svg/opengl/framebufferobject/
 - Run in terminal env QT_QPA_PLATFORM=wayland-egl WAYLAND_DEBUG=client ./framebufferobject
 - Move application window to another workspace, go back to the workspace with the terminal (so that the application stays on an inactive workspace).
 - Observe how Qt keeps creating new wl_callback objects with constantly increasing id
 - Once callback id reaches ~10000, switch to the workspace with the application
 - Observe how application dies with 'The wayland connection broke. Did the Wayland compositor die?'
 
| For Gerrit Dashboard: QTBUG-81504 | ||||||
|---|---|---|---|---|---|---|
| # | Subject | Branch | Project | Status | CR | V | 
| 343864,2 | client: Fix frame callback leak when window unexposed | dev | qt/qtwayland | Status: MERGED | +2 | 0 | 
| 351447,5 | Client: Don't always recreate frame callbacks | dev | qt/qtwayland | Status: MERGED | +2 | 0 | 
| 352664,2 | Fix conversion of swap interval from QGLFormat to QSurfaceFormat | tqtc/lts-5.15 | qt/tqtc-qtbase | Status: MERGED | +2 | 0 | 
| 425889,1 | WIP backport: Client: Don't always recreate frame callbacks | tqtc/lts-5.15 | qt/tqtc-qtwayland | Status: DEFERRED | 0 | 0 |