xwayland: Delay wl_surface destruction
X11 and Wayland requests are unordered, causing a race in the X11 window and wl_surface association. To mitigate that race, delay the wl_surface destruction by 1 second, so that the compositor has time to establish the association before the wl_surface is destroyed: to see both the wl_surface created and the WL_SURFACE_ID X11 property set. This is only a mitigation though, a more robust solution requires a future dedicated Wayland protocol. v2: Clean up pending wl_surface destroy on exit as well. Closes: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1157 Signed-off-by: Olivier Fourdan <ofourdan@redhat.com> Suggested-by: Pekka Paalanen <pekka.paalanen@collabora.com> Reviewed-by: Michel Dänzer <mdaenzer@redhat.com> Tested-by: Joshua Ashton <joshua@froggi.es> Tested-by: Sterophonick <sterophonick@gmail.com> See-also: https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/163
This commit is contained in:
parent
01b8396d73
commit
e37f18ee97
|
@ -182,6 +182,7 @@ xwl_close_screen(ScreenPtr screen)
|
|||
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
|
||||
struct xwl_output *xwl_output, *next_xwl_output;
|
||||
struct xwl_seat *xwl_seat, *next_xwl_seat;
|
||||
struct xwl_wl_surface *xwl_wl_surface, *xwl_wl_surface_next;
|
||||
|
||||
DeleteCallback(&PropertyStateCallback, xwl_property_callback, screen);
|
||||
|
||||
|
@ -204,6 +205,10 @@ xwl_close_screen(ScreenPtr screen)
|
|||
xwl_screen_destroy_drm_lease_device(xwl_screen,
|
||||
device_data->drm_lease_device);
|
||||
|
||||
xorg_list_for_each_entry_safe(xwl_wl_surface, xwl_wl_surface_next,
|
||||
&xwl_screen->pending_wl_surface_destroy, link)
|
||||
xwl_window_surface_do_destroy(xwl_wl_surface);
|
||||
|
||||
RemoveNotifyFd(xwl_screen->wayland_fd);
|
||||
|
||||
wl_display_disconnect(xwl_screen->display);
|
||||
|
@ -818,6 +823,7 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
|
|||
xorg_list_init(&xwl_screen->drm_lease_devices);
|
||||
xorg_list_init(&xwl_screen->queued_drm_lease_devices);
|
||||
xorg_list_init(&xwl_screen->drm_leases);
|
||||
xorg_list_init(&xwl_screen->pending_wl_surface_destroy);
|
||||
xwl_screen->depth = 24;
|
||||
|
||||
if (!monitorResolution)
|
||||
|
|
|
@ -107,6 +107,7 @@ struct xwl_screen {
|
|||
struct xorg_list queued_drm_lease_devices;
|
||||
struct xorg_list drm_leases;
|
||||
struct xwl_output *fixed_output;
|
||||
struct xorg_list pending_wl_surface_destroy;
|
||||
uint32_t serial;
|
||||
|
||||
#define XWL_FORMAT_ARGB8888 (1 << 0)
|
||||
|
|
|
@ -46,6 +46,8 @@
|
|||
#include "viewporter-client-protocol.h"
|
||||
#include "xdg-shell-client-protocol.h"
|
||||
|
||||
#define DELAYED_WL_SURFACE_DESTROY 1000 /* ms */
|
||||
|
||||
static DevPrivateKeyRec xwl_window_private_key;
|
||||
static DevPrivateKeyRec xwl_damage_private_key;
|
||||
static const char *xwl_surface_tag = "xwl-surface";
|
||||
|
@ -852,6 +854,58 @@ xwl_realize_window(WindowPtr window)
|
|||
return ensure_surface_for_window(window);
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_surface_destroy_free_timer(struct xwl_wl_surface *xwl_wl_surface)
|
||||
{
|
||||
if (xwl_wl_surface->wl_surface_destroy_timer) {
|
||||
TimerFree(xwl_wl_surface->wl_surface_destroy_timer);
|
||||
xwl_wl_surface->wl_surface_destroy_timer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
xwl_window_surface_do_destroy(struct xwl_wl_surface *xwl_wl_surface)
|
||||
{
|
||||
wl_surface_destroy(xwl_wl_surface->wl_surface);
|
||||
xorg_list_del(&xwl_wl_surface->link);
|
||||
xwl_surface_destroy_free_timer(xwl_wl_surface);
|
||||
free(xwl_wl_surface);
|
||||
}
|
||||
|
||||
static CARD32
|
||||
xwl_surface_destroy_callback(OsTimerPtr timer, CARD32 now, void *arg)
|
||||
{
|
||||
struct xwl_wl_surface *xwl_wl_surface = arg;
|
||||
|
||||
xwl_window_surface_do_destroy(xwl_wl_surface);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
release_wl_surface_for_window(struct xwl_window *xwl_window)
|
||||
{
|
||||
struct xwl_wl_surface *xwl_wl_surface;
|
||||
|
||||
/* If the Xserver is terminating, destroy the surface immediately */
|
||||
if ((dispatchException & DE_TERMINATE) == DE_TERMINATE) {
|
||||
wl_surface_destroy(xwl_window->surface);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Otherwise, schedule the destruction later, to mitigate the race
|
||||
* between X11 and Wayland processing so that the compositor has the
|
||||
* time to establish the association before the wl_surface is destroyed.
|
||||
*/
|
||||
xwl_wl_surface = xnfcalloc(1, sizeof *xwl_wl_surface);
|
||||
xwl_wl_surface->wl_surface = xwl_window->surface;
|
||||
xorg_list_add(&xwl_wl_surface->link,
|
||||
&xwl_window->xwl_screen->pending_wl_surface_destroy);
|
||||
xwl_wl_surface->wl_surface_destroy_timer =
|
||||
TimerSet(NULL, 0, DELAYED_WL_SURFACE_DESTROY,
|
||||
xwl_surface_destroy_callback, xwl_wl_surface);
|
||||
}
|
||||
|
||||
Bool
|
||||
xwl_unrealize_window(WindowPtr window)
|
||||
{
|
||||
|
@ -906,7 +960,7 @@ xwl_unrealize_window(WindowPtr window)
|
|||
}
|
||||
#endif
|
||||
|
||||
wl_surface_destroy(xwl_window->surface);
|
||||
release_wl_surface_for_window(xwl_window);
|
||||
xorg_list_del(&xwl_window->link_damage);
|
||||
xorg_list_del(&xwl_window->link_window);
|
||||
unregister_damage(window);
|
||||
|
|
|
@ -37,6 +37,12 @@
|
|||
|
||||
#include "xwayland-types.h"
|
||||
|
||||
struct xwl_wl_surface {
|
||||
OsTimerPtr wl_surface_destroy_timer;
|
||||
struct wl_surface *wl_surface;
|
||||
struct xorg_list link;
|
||||
};
|
||||
|
||||
struct xwl_window {
|
||||
struct xwl_screen *xwl_screen;
|
||||
struct wl_surface *surface;
|
||||
|
@ -91,6 +97,8 @@ void xwl_move_window(WindowPtr window,
|
|||
Bool xwl_destroy_window(WindowPtr window);
|
||||
void xwl_window_post_damage(struct xwl_window *xwl_window);
|
||||
void xwl_window_create_frame_callback(struct xwl_window *xwl_window);
|
||||
void xwl_window_surface_do_destroy(struct xwl_wl_surface *xwl_wl_surface);
|
||||
|
||||
Bool xwl_window_init(void);
|
||||
|
||||
#endif /* XWAYLAND_WINDOW_H */
|
||||
|
|
Loading…
Reference in New Issue