[PATCH weston] libweston-desktop/xwayland: Make sure racy surfaces are properly mapped

Quentin Glidic sardemff7+wayland at sardemff7.net
Fri Jul 21 16:43:41 UTC 2017


On 5/15/17 4:40 PM, Pekka Paalanen wrote:
> On Mon, 15 May 2017 15:29:29 +0200
> Quentin Glidic <sardemff7+wayland at sardemff7.net> wrote:
> 
>> From: Quentin Glidic <sardemff7+git at sardemff7.net>
>>
>> Signed-off-by: Quentin Glidic <sardemff7+git at sardemff7.net>
>> ---
>>   libweston-desktop/xwayland.c | 10 ++++++++++
>>   1 file changed, 10 insertions(+)
>>
>> diff --git a/libweston-desktop/xwayland.c b/libweston-desktop/xwayland.c
>> index 4f4b453f..4dcb5f03 100644
>> --- a/libweston-desktop/xwayland.c
>> +++ b/libweston-desktop/xwayland.c
>> @@ -61,6 +61,7 @@ struct weston_desktop_xwayland_surface {
>>   	const struct weston_xwayland_client_interface *client_interface;
>>   	struct weston_geometry next_geometry;
>>   	bool has_next_geometry;
>> +	bool committed;
>>   	bool added;
>>   	enum weston_desktop_xwayland_surface_state state;
>>   };
>> @@ -99,6 +100,14 @@ weston_desktop_xwayland_surface_change_state(struct weston_desktop_xwayland_surf
>>   			weston_desktop_api_surface_added(surface->desktop,
>>   							 surface->surface);
>>   			surface->added = true;
>> +			if (surface->state == NONE && surface->committed)
>> +				/* We had a race, and wl_surface.commit() was
>> +				 * faster, just fake a commit to map the
>> +				 * surface */
>> +				weston_desktop_api_committed(surface->desktop,
>> +							     surface->surface,
>> +							     0, 0);
>> +
>>   		} else if (surface->added) {
>>   			weston_desktop_api_surface_removed(surface->desktop,
>>   							   surface->surface);
>> @@ -134,6 +143,7 @@ weston_desktop_xwayland_surface_committed(struct weston_desktop_surface *dsurfac
>>   	struct weston_geometry oldgeom;
>>   
>>   	assert(dsurface == surface->surface);
>> +	surface->committed = true;
>>   
>>   #ifdef WM_DEBUG
>>   	weston_log("%s: xwayland surface %p\n", __func__, surface);
> 
> Hi Quentin,
> 
> thanks for making the patch so fast! It clarified my thoughts.
> 
> I wonder, could it become a problem to never unset 'committed'? In case
> something causes XWM or Xwayland to "unmap" the surface and later map
> again.
 >
> We'd want to check for "has content", and checking for a buffer is not
> always right as the renderer may have made a copy and released the
> buffer, so... weston_surface width and height > 0?
> 
> Calling weston_desktop_api_commit() sounds like the right solution.
> 
> Is surface->state reset back to NONE when the surface is unmapped? What
> about !weston_surface_is_mapped()?
> 
> 
> I feel I should explain more background for the bug we are trying to
> fix here, as I have no reliable way to reproduce. Hopefully that
> inspires a commit message. ;-)
> 
> The question is about a fundamental race between the Wayland and X11
> protocol streams for XWM. Wayland carries the surface content, which is
> latched in with wl_surface.commit that leads to calling into the shell
> plugin to map the window. X11 carries the window management
> information, essentially the shell role for the window/surface.
> Obviously we cannot actually map a window until it has both content and
> role.
> 
> So the race is between setting the content and setting the role. IIRC
> e.g. xdg_shell simply forbids this race, requiring role to be set
> first. Unfortunately with Xwayland I don't think we have the luxury of
> that. There is the _XWAYLAND_ALLOW_COMMITS feature which could mitigate
> the problem, but it is not yet in any xorg-xserver release, and we need
> to be able to do without it.
> 
> The actual bug is, that if content is set first, setting the role does
> not complete mapping the surface. As the surface is not mapped, the frame
> callbacks are not sent, and Xwayland will never commit again. The
> window is lost in an unmapped limbo.
> 
> At least, I believe we have that bug. Actually I am helping to fix this
> bug on Weston 1.11 which is before the introduction of
> libweston-desktop. I have had reports of this issue on 1.11, and when I
> looked at the code in master, I believe the problem is still there, but
> have not been able to reproduce it. Doesn't help that I'm generally
> running with _XWAYLAND_ALLOW_COMMITS support too.

Actually, the concepts involved don’t match the code perfectly.
In libweston-desktop, the commit does *not* depend on content. It just 
happens that Xwayland commit for content only (since the rest is done 
via XWM). The compositor/shell has to deal with NULL-buffer surfaces 
anyway, since wl_shell mandates that.

Mapping the surface needs this sequence:
1. libweston-desktop surface_added callback
2. libweston-desktop committed callback

Unmapping a surface, if I understand XWM enough, will destroy the 
wl_surface and reset the desktop surface to NULL. That means creating a 
new weston_desktop_surface on remap.

So the race can really only happen the first time the X window is 
created and committed.
No code leads to reset the weston_desktop_surface to NONE, it has to be 
a new one.

So, AFAICT, this patch will just work™.

Most of libweston-desktop xwayland code was copied from shell.c, though 
a bit modified since then, so it may be easy to do exactly the same.

Cheers,

-- 

Quentin “Sardem FF7” Glidic


More information about the wayland-devel mailing list