Repository navigation
fix: prevent gnome-shell crash when closing windows on Wayland - #586
Open
GilJSantana wants to merge 1 commit into
Open
GilJSantana wants to merge 1 commit into
GilJSantana wants to merge 1 commit into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fix gnome-shell crash (session logout) when closing a window on Wayland
Problem
On GNOME Shell 51 / Mutter 51 (Wayland), opening a second application and then closing it crashes
gnome-shell. The user is logged out and sent back to GDM.Steps to reproduce:
gnome-shellcrashes. GDM restarts, then a new user session starts.The journal shows no JS exception before the crash. There is a burst of:
…then the process dies, and you see
Running GNOME Shell (using mutter 51.0)again for GDM and then for the new session.Environment: GNOME Shell 51.0, Mutter 51.0, Wayland, Forge
main@1bf4b21.Root cause
Forge calls Mutter APIs on
MetaWindows that are not ready yet or are already being unmanaged:unmanagingandunmanaged. The actor emitsdestroyonly after the close animation. Forge removed the node only inwindowDestroy(the actordestroy), so during the animation the dead window stayed in the tree. AnyrenderTree()then calledmove_resize_frame()/unmaximize()on it.windowDestroyalso calledremoveFloatOverride()(get_wm_class(),get_id()) on the unmanaged window. The per-window signals were never disconnected.create/renderpaths moved windows before their first buffer. That is the source of thepriv->is_readywarnings.global.get_window_actors()includes actors of windows that are still animating closed. The loop calledfocus()/raise()on them. It also refocused the same window on every tick.Changes (
lib/extension/window.jsonly)Window lifecycle
_isAlive(),_isMaximized(),_unmaximize(),_destroyActorDecorations(),_disconnectWindowSignals().unmanagingsignal (new_onWindowUnmanaging(), replacing theunmanagedhandler). It does the following:windowDestroy()is now only a safety net. It no longer calls into theMetaWindow.Readiness gating
move()returns early unless the window is alive and ready. It also no longer callsmove_frame()beforemove_resize_frame(), unmaximizes only when the window is maximized, and rounds the rect.first-frame, the window'sshown, or a 500 ms safety timeout (_watchWindowReady()). Becoming ready triggers arenderTree(). Windows that already exist when Forge is enabled are marked ready intrackCurrentWindows().window-createdis emitted before the compositor actor exists.trackWindow()now defers tracking until the actor appears (_deferTrackWindow():shownsignal plus a 50 ms poll, giving up after about 5 s) instead of dropping the window._liveResizeNeighbors()/_startLiveResizeLoop()) callsmove_resize_frame()directly. It now skips windows that are not alive or not ready.Focus on hover
_getMetaWindowAtPointer()ignores hidden, minimized, unmanaged and non-normal windows. It uses the frame rect.focus()/raise()are called only when the window under the pointer changes.this.grabOpis reset at the end of a grab, so the loop resumes after a drag.Smaller fixes found along the way
showWindowBorders():!maximized→!maximized(). It was a function reference, so it was always false and the split border never showed.updateMetaWorkspaceMonitor():!this.grabOp === Meta.GrabOp.WINDOW_BASE→this.grabOp !== …. The old check was always false.SnapLayoutMove:breakmoved out of theif. Without a focused window it fell through intoShowTabDecorationToggle.postProcessWindow()passed theMetaWindowtomovePointerWith()instead of the node.warpPointerToNodeWindow(): gets the seat fromglobal.stage.context.get_backend(), falling back toClutter.get_default_backend(), and is wrapped in try/catch.command(),rectForMonitor(),getWindowsOnWorkspace(),hideWindowBorders(),WindowSwapLastActiveand others.caseblocks withletdeclarations are wrapped in braces.Testing
Tested on GNOME Shell 51.0 / Mutter 51.0, Wayland:
meta_window_move_resize_internal: runtime check failed: (priv->is_ready)in the journal.npm test(prettier--list-different) passes forlib/extension/window.js.Happy to split this into smaller PRs, for example (1) the lifecycle and crash fix and (2) the small bug fixes, if that is easier to review.