May 6, 2016 - Mike Blumenkrantz
Wayland Recovery: A Journey Of Discovery
Wayland on the desktop is a constantly evolving project. Whether it’s improvements to the drag-n-drop protocol or extreme functionality enhancements in the client-side decorations, Wayland is a fast-moving target which allows developers to shape it in almost any way they desire.
However, there are some limitations to a Wayland compositor when compared to X11 window managers. Under X11, a window manager is just a client of the XServer; this allows it to do things like restart itself without killing the user’s session. In Wayland, a restart of the running session’s compositor disconnects all the active clients, causing them to terminate. This increases the difficulty of things like crash handling where the environment can gracefully restart itself if there’s a crash.
How to Crash Gracefully
This is where a newly-created extension comes into play: the Session Recovery Extension. With Session Recovery enabled, a client is able to reconnect to the compositor after a new instance has been created, creating all surfaces anew and preserving internal draw states. The compositor remembers the client’s window states and reapplies them after the restart, creating a seamless restart experience.
The Session Recovery Extension is implemented in two parts: the compositor and the client. Clients request compositor-generated IDs to tag their surfaces across sessions, and the compositor uses these IDs to resume the client’s window states: geometry, layering, screen, virtual desktop, etc. In Enlightenment’s implementation, libuuid is used by the compositor to generate uuids that are used as this ID. The client has three methods: ‘get_uuid’, ‘set_uuid’, and ‘destroy_uuid’.
‘get_uuid’ requests a new ID (uuid) for a surface from the compositor. The compositor generates a uuid, creates a new tracking instance for the surface, and sends the uuid back to the client.
‘set_uuid’ sends a generated uuid back to the compositor, requesting that the existing session info be applied to it. If the compositor verifies the uuid successfully the surface info is reapplied to restore its previous states.
‘destroy_uuid’ removes a stored surface ID from the session, preventing it from being used again.
In the current implementation, an ID is tied to the client’s process ID, allowing a match for a surface only if it belongs to the PID of the previous session’s surface. This reduces the chances that a client can spoof another client’s session ID while staying within “safe” information provided within the Wayland protocol.
The compositor-side implementation of this is fairly straightforward: tag surfaces with IDs, track and store the states, reapply states after validating a restore request. The client-side rendering parts are a bit more complicated, however.
Now Supported: Client-Side Crashing!
The basic operation when using a retained mode canvas would be for the rendering engine to trigger a full surface render flush after reconnecting, preserving all existing draw states and using the least amount of CPU to resume the session. This is fine when using a software renderer, but when GL is added it becomes trickier.
EGL contexts in Wayland are created based on the Wayland display that is connected, meaning that any time the display is destroyed, the context must also be destroyed. In the case of EFL, a global EGL context is used across all windows, covering all textures created from images and related objects. When the display is disconnected, that context must be destroyed and all corresponding object data must be deleted. Then, after reconnect, a new context must be bound and the object data regenerated. All of this must be done while preventing any rendering from occurring to prevent invalid operations from being attempted when the render engine tries to push surface data to the compositor.
If all of this is done correctly and at the right time the result is that the existing session will be preserved for applications that support it. Applications that do not support it will, regrettably, still terminate themselves upon being disconnected from the server.
This sort of technology provides improvements to the desktop experience, but it could also be applied to other places as well. When shipping embedded devices session recovery could ensure that any corner-case bugs that were not resolved prior to product shipment do not impact the user experience as severely. Alternatively, it can allow the compositor to upgrade itself without losing the session, something that is increasingly necessary in today’s world of ubiquitous software updating.
Wayland might not have widespread adoption on the desktop at this time, but its flexibility and active developer community is pointing to a bright future for the project.
About Mike Blumenkrantz
Mike is the release manager for Enlightenment as well as a core developer of the EFL toolkit. He sometimes contributes to the Servo application embedding API/ABI, and in his free time he attempts to write desktop applications.
Image Credits: Kristian Høgsberg