<div dir="ltr">Hi Pekka,<div><br></div><div>Thanks for the explanation. You're probably right; this shouldn't be possible.</div><div><br></div><div>I haven't been able to reproduce the bug again. The one time I got it was when I was working on my show_window_menu patches - so it's quite possible that something there was causing it. (In fact, the window menu involves two different clients - the owner of the window and the desktop shell - so maybe that was the problem.)</div><div><br></div><div>Anyways, let's ignore this patch unless I figure out what actually happened there.</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Dec 5, 2016 at 3:12 AM, Pekka Paalanen <span dir="ltr"><<a href="mailto:ppaalanen@gmail.com" target="_blank">ppaalanen@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On Sat, 3 Dec 2016 21:21:44 -0800<br>
Dima Ryazanov <<a href="mailto:dima@gmail.com">dima@gmail.com</a>> wrote:<br>
<br>
> This should fix some (fairly rare) crashes where the client goes away at exactly<br>
> the wrong moment, e.g.:<br>
> - Weston sends a message to the client<br>
> - Message causes the client to crash for whatever reason<br>
> - Weston keeps processing the remaining requests from the now dead client<br>
<br>
</span>Hi,<br>
<br>
I'm curious. Even if the client crashes, this should happen:<br>
<br>
1. the server processes queued requests while it is not aware of the<br>
client going away<br>
2. libwayland-server notices the client has gone away, and calls<br>
destructors on all objects<br>
<br>
During step 1, the client being already dead does not affect anything<br>
because the disconnection has not been processed, so any user data<br>
still remains valid.<br>
<br>
Once the destruction begins, no requests should dispatch anymore. If<br>
some requests are still being dispatched, that would be a bug in<br>
libwayland-server.<br>
<br>
I'd really like to know how it is possible to have these functions<br>
called with invalid user data. I fear that this patch might just paper<br>
over some real bugs.<br>
<br>
Resources do not just go away, especially those that represent objects<br>
created by the client. I can understand that wl_output user data can be<br>
NULL if the weston_output has been destroyed, but not with e.g.<br>
wl_surface since the surface is created by the client, so it cannot go<br>
away without the client destroying it or disconnecting.<br>
<br>
Could there perhaps be some object destruction sequence that e.g.<br>
libweston-desktop does not handle? Is that what is going on here?<br>
<br>
Does the protocol define a destruction order, should we be sending<br>
protocol errors somewhere?<br>
<span class=""><br>
> (I've only seen it happen once, while stepping through Weston's code in gdb, but<br>
> seems like the right thing to fix.)<br>
<br>
</span>Stepping in gdb only makes Weston extremely slow to execute, so it can<br>
expose races or trigger "unresponsive client" etc. timeouts, but it<br>
does not affect steps 1 and 2 mentioned above. So if there is a race,<br>
we need to fix the race instead.<br>
<br>
Hence, I'm not yet convinced this patch is the right thing to do.<br>
<br>
On the contrary, without any other explanation I would expect the checks<br>
you added to be asserts instead of silently ignoring the unexpected.<br>
<br>
<br>
Thanks,<br>
pq<br>
<div class="HOEnZb"><div class="h5"><br>
<br>
> Signed-off-by: Dima Ryazanov <<a href="mailto:dima@gmail.com">dima@gmail.com</a>><br>
> ---<br>
> libweston-desktop/xdg-shell-<wbr>v6.c | 141 ++++++++++++++++++++++++++++--<wbr>---------<br>
> 1 file changed, 101 insertions(+), 40 deletions(-)<br>
><br>
> diff --git a/libweston-desktop/xdg-shell-<wbr>v6.c b/libweston-desktop/xdg-shell-<wbr>v6.c<br>
> index 7d0bd8e..30f6d82 100644<br>
> --- a/libweston-desktop/xdg-shell-<wbr>v6.c<br>
> +++ b/libweston-desktop/xdg-shell-<wbr>v6.c<br>
> @@ -302,10 +302,14 @@ weston_desktop_xdg_toplevel_<wbr>protocol_set_parent(struct wl_client *wl_client,<br>
> {<br>
> struct weston_desktop_surface *dsurface =<br>
> wl_resource_get_user_data(<wbr>resource);<br>
> - struct weston_desktop_xdg_toplevel *toplevel =<br>
> - weston_desktop_surface_get_<wbr>implementation_data(dsurface);<br>
> + struct weston_desktop_xdg_toplevel *toplevel;<br>
> struct weston_desktop_surface *parent = NULL;<br>
><br>
> + if (!dsurface)<br>
> + return;<br>
> +<br>
> + toplevel = weston_desktop_surface_get_<wbr>implementation_data(dsurface);<br>
> +<br>
> if (parent_resource != NULL)<br>
> parent = wl_resource_get_user_data(<wbr>parent_resource);<br>
><br>
> @@ -346,8 +350,12 @@ weston_desktop_xdg_toplevel_<wbr>protocol_show_window_menu(<wbr>struct wl_client *wl_clien<br>
> wl_resource_get_user_data(<wbr>resource);<br>
> struct weston_seat *seat =<br>
> wl_resource_get_user_data(<wbr>seat_resource);<br>
> - struct weston_desktop_xdg_toplevel *toplevel =<br>
> - weston_desktop_surface_get_<wbr>implementation_data(dsurface);<br>
> + struct weston_desktop_xdg_toplevel *toplevel;<br>
> +<br>
> + if (!dsurface)<br>
> + return;<br>
> +<br>
> + toplevel = weston_desktop_surface_get_<wbr>implementation_data(dsurface);<br>
><br>
> if (!toplevel->base.configured) {<br>
> wl_resource_post_error(<wbr>toplevel->resource,<br>
> @@ -370,8 +378,12 @@ weston_desktop_xdg_toplevel_<wbr>protocol_move(struct wl_client *wl_client,<br>
> wl_resource_get_user_data(<wbr>resource);<br>
> struct weston_seat *seat =<br>
> wl_resource_get_user_data(<wbr>seat_resource);<br>
> - struct weston_desktop_xdg_toplevel *toplevel =<br>
> - weston_desktop_surface_get_<wbr>implementation_data(dsurface);<br>
> + struct weston_desktop_xdg_toplevel *toplevel;<br>
> +<br>
> + if (!dsurface)<br>
> + return;<br>
> +<br>
> + toplevel = weston_desktop_surface_get_<wbr>implementation_data(dsurface);<br>
><br>
> if (!toplevel->base.configured) {<br>
> wl_resource_post_error(<wbr>toplevel->resource,<br>
> @@ -394,11 +406,15 @@ weston_desktop_xdg_toplevel_<wbr>protocol_resize(struct wl_client *wl_client,<br>
> wl_resource_get_user_data(<wbr>resource);<br>
> struct weston_seat *seat =<br>
> wl_resource_get_user_data(<wbr>seat_resource);<br>
> - struct weston_desktop_xdg_toplevel *toplevel =<br>
> - weston_desktop_surface_get_<wbr>implementation_data(dsurface);<br>
> + struct weston_desktop_xdg_toplevel *toplevel;<br>
> enum weston_desktop_surface_edge surf_edges =<br>
> (enum weston_desktop_surface_edge) edges;<br>
><br>
> + if (!dsurface)<br>
> + return;<br>
> +<br>
> + toplevel = weston_desktop_surface_get_<wbr>implementation_data(dsurface);<br>
> +<br>
> if (!toplevel->base.configured) {<br>
> wl_resource_post_error(<wbr>toplevel->resource,<br>
> ZXDG_SURFACE_V6_ERROR_NOT_<wbr>CONSTRUCTED,<br>
> @@ -423,9 +439,12 @@ weston_desktop_xdg_toplevel_<wbr>protocol_set_min_size(struct wl_client *wl_client,<br>
> {<br>
> struct weston_desktop_surface *dsurface =<br>
> wl_resource_get_user_data(<wbr>resource);<br>
> - struct weston_desktop_xdg_toplevel *toplevel =<br>
> - weston_desktop_surface_get_<wbr>implementation_data(dsurface);<br>
> + struct weston_desktop_xdg_toplevel *toplevel;<br>
><br>
> + if (!dsurface)<br>
> + return;<br>
> +<br>
> + toplevel = weston_desktop_surface_get_<wbr>implementation_data(dsurface);<br>
> toplevel->next_min_size.width = width;<br>
> toplevel->next_min_size.height = height;<br>
> }<br>
> @@ -437,9 +456,12 @@ weston_desktop_xdg_toplevel_<wbr>protocol_set_max_size(struct wl_client *wl_client,<br>
> {<br>
> struct weston_desktop_surface *dsurface =<br>
> wl_resource_get_user_data(<wbr>resource);<br>
> - struct weston_desktop_xdg_toplevel *toplevel =<br>
> - weston_desktop_surface_get_<wbr>implementation_data(dsurface);<br>
> + struct weston_desktop_xdg_toplevel *toplevel;<br>
> +<br>
> + if (!dsurface)<br>
> + return;<br>
><br>
> + toplevel = weston_desktop_surface_get_<wbr>implementation_data(dsurface);<br>
> toplevel->next_max_size.width = width;<br>
> toplevel->next_max_size.height = height;<br>
> }<br>
> @@ -450,9 +472,12 @@ weston_desktop_xdg_toplevel_<wbr>protocol_set_maximized(struct wl_client *wl_client,<br>
> {<br>
> struct weston_desktop_surface *dsurface =<br>
> wl_resource_get_user_data(<wbr>resource);<br>
> - struct weston_desktop_xdg_toplevel *toplevel =<br>
> - weston_desktop_surface_get_<wbr>implementation_data(dsurface);<br>
> + struct weston_desktop_xdg_toplevel *toplevel;<br>
><br>
> + if (!dsurface)<br>
> + return;<br>
> +<br>
> + toplevel = weston_desktop_surface_get_<wbr>implementation_data(dsurface);<br>
> weston_desktop_xdg_toplevel_<wbr>ensure_added(toplevel);<br>
> weston_desktop_api_maximized_<wbr>requested(toplevel->base.<wbr>desktop, dsurface, true);<br>
> }<br>
> @@ -463,9 +488,12 @@ weston_desktop_xdg_toplevel_<wbr>protocol_unset_maximized(<wbr>struct wl_client *wl_client<br>
> {<br>
> struct weston_desktop_surface *dsurface =<br>
> wl_resource_get_user_data(<wbr>resource);<br>
> - struct weston_desktop_xdg_toplevel *toplevel =<br>
> - weston_desktop_surface_get_<wbr>implementation_data(dsurface);<br>
> + struct weston_desktop_xdg_toplevel *toplevel;<br>
> +<br>
> + if (!dsurface)<br>
> + return;<br>
><br>
> + toplevel = weston_desktop_surface_get_<wbr>implementation_data(dsurface);<br>
> weston_desktop_xdg_toplevel_<wbr>ensure_added(toplevel);<br>
> weston_desktop_api_maximized_<wbr>requested(toplevel->base.<wbr>desktop, dsurface, false);<br>
> }<br>
> @@ -477,10 +505,14 @@ weston_desktop_xdg_toplevel_<wbr>protocol_set_fullscreen(struct wl_client *wl_client,<br>
> {<br>
> struct weston_desktop_surface *dsurface =<br>
> wl_resource_get_user_data(<wbr>resource);<br>
> - struct weston_desktop_xdg_toplevel *toplevel =<br>
> - weston_desktop_surface_get_<wbr>implementation_data(dsurface);<br>
> + struct weston_desktop_xdg_toplevel *toplevel;<br>
> struct weston_output *output = NULL;<br>
><br>
> + if (!dsurface)<br>
> + return;<br>
> +<br>
> + toplevel = weston_desktop_surface_get_<wbr>implementation_data(dsurface);<br>
> +<br>
> if (output_resource != NULL)<br>
> output = wl_resource_get_user_data(<wbr>output_resource);<br>
><br>
> @@ -495,9 +527,12 @@ weston_desktop_xdg_toplevel_<wbr>protocol_unset_fullscreen(<wbr>struct wl_client *wl_clien<br>
> {<br>
> struct weston_desktop_surface *dsurface =<br>
> wl_resource_get_user_data(<wbr>resource);<br>
> - struct weston_desktop_xdg_toplevel *toplevel =<br>
> - weston_desktop_surface_get_<wbr>implementation_data(dsurface);<br>
> + struct weston_desktop_xdg_toplevel *toplevel;<br>
> +<br>
> + if (!dsurface)<br>
> + return;<br>
><br>
> + toplevel = weston_desktop_surface_get_<wbr>implementation_data(dsurface);<br>
> weston_desktop_xdg_toplevel_<wbr>ensure_added(toplevel);<br>
> weston_desktop_api_fullscreen_<wbr>requested(toplevel->base.<wbr>desktop, dsurface,<br>
> false, NULL);<br>
> @@ -509,9 +544,12 @@ weston_desktop_xdg_toplevel_<wbr>protocol_set_minimized(struct wl_client *wl_client,<br>
> {<br>
> struct weston_desktop_surface *dsurface =<br>
> wl_resource_get_user_data(<wbr>resource);<br>
> - struct weston_desktop_xdg_toplevel *toplevel =<br>
> - weston_desktop_surface_get_<wbr>implementation_data(dsurface);<br>
> + struct weston_desktop_xdg_toplevel *toplevel;<br>
><br>
> + if (!dsurface)<br>
> + return;<br>
> +<br>
> + toplevel = weston_desktop_surface_get_<wbr>implementation_data(dsurface);<br>
> weston_desktop_xdg_toplevel_<wbr>ensure_added(toplevel);<br>
> weston_desktop_api_minimized_<wbr>requested(toplevel->base.<wbr>desktop, dsurface);<br>
> }<br>
> @@ -737,12 +775,19 @@ weston_desktop_xdg_popup_<wbr>protocol_grab(struct wl_client *wl_client,<br>
> {<br>
> struct weston_desktop_surface *dsurface =<br>
> wl_resource_get_user_data(<wbr>resource);<br>
> - struct weston_desktop_xdg_popup *popup =<br>
> - weston_desktop_surface_get_<wbr>implementation_data(dsurface);<br>
> + struct weston_desktop_xdg_popup *popup;<br>
> struct weston_seat *wseat = wl_resource_get_user_data(<wbr>seat_resource);<br>
> - struct weston_desktop_seat *seat = weston_desktop_seat_from_seat(<wbr>wseat);<br>
> + struct weston_desktop_seat *seat;<br>
> struct weston_desktop_surface *topmost;<br>
> - bool parent_is_toplevel =<br>
> + bool parent_is_toplevel;<br>
> +<br>
> + if (!dsurface || !wseat)<br>
> + return;<br>
> +<br>
> + seat = weston_desktop_seat_from_seat(<wbr>wseat);<br>
> + popup = weston_desktop_surface_get_<wbr>implementation_data(dsurface);<br>
> +<br>
> + parent_is_toplevel =<br>
> popup->parent->role == WESTON_DESKTOP_XDG_SURFACE_<wbr>ROLE_TOPLEVEL;<br>
><br>
> if (popup->committed) {<br>
> @@ -891,10 +936,14 @@ weston_desktop_xdg_surface_<wbr>protocol_get_toplevel(struct wl_client *wl_client,<br>
> {<br>
> struct weston_desktop_surface *dsurface =<br>
> wl_resource_get_user_data(<wbr>resource);<br>
> - struct weston_surface *wsurface =<br>
> - weston_desktop_surface_get_<wbr>surface(dsurface);<br>
> - struct weston_desktop_xdg_toplevel *toplevel =<br>
> - weston_desktop_surface_get_<wbr>implementation_data(dsurface);<br>
> + struct weston_surface *wsurface;<br>
> + struct weston_desktop_xdg_toplevel *toplevel;<br>
> +<br>
> + if (!dsurface)<br>
> + return;<br>
> +<br>
> + toplevel = weston_desktop_surface_get_<wbr>implementation_data(dsurface);<br>
> + wsurface = weston_desktop_surface_get_<wbr>surface(dsurface);<br>
><br>
> if (weston_surface_set_role(<wbr>wsurface, weston_desktop_xdg_toplevel_<wbr>role,<br>
> resource, ZXDG_SHELL_V6_ERROR_ROLE) < 0)<br>
> @@ -920,17 +969,21 @@ weston_desktop_xdg_surface_<wbr>protocol_get_popup(struct wl_client *wl_client,<br>
> {<br>
> struct weston_desktop_surface *dsurface =<br>
> wl_resource_get_user_data(<wbr>resource);<br>
> - struct weston_surface *wsurface =<br>
> - weston_desktop_surface_get_<wbr>surface(dsurface);<br>
> - struct weston_desktop_xdg_popup *popup =<br>
> - weston_desktop_surface_get_<wbr>implementation_data(dsurface);<br>
> + struct weston_surface *wsurface;<br>
> + struct weston_desktop_xdg_popup *popup;<br>
> struct weston_desktop_surface *parent_surface =<br>
> wl_resource_get_user_data(<wbr>parent_resource);<br>
> - struct weston_desktop_xdg_surface *parent =<br>
> - weston_desktop_surface_get_<wbr>implementation_data(parent_<wbr>surface);<br>
> + struct weston_desktop_xdg_surface *parent;<br>
> struct weston_desktop_xdg_positioner *positioner =<br>
> wl_resource_get_user_data(<wbr>positioner_resource);<br>
><br>
> + if (!dsurface || !parent_surface || !positioner)<br>
> + return;<br>
> +<br>
> + wsurface = weston_desktop_surface_get_<wbr>surface(dsurface);<br>
> + popup = weston_desktop_surface_get_<wbr>implementation_data(dsurface);<br>
> + parent = weston_desktop_surface_get_<wbr>implementation_data(parent_<wbr>surface);<br>
> +<br>
> /* Checking whether the size and anchor rect both have a positive size<br>
> * is enough to verify both have been correctly set */<br>
> if (positioner->size.width == 0 || positioner->anchor_rect.width == 0) {<br>
> @@ -994,8 +1047,12 @@ weston_desktop_xdg_surface_<wbr>protocol_set_window_geometry(<wbr>struct wl_client *wl_cli<br>
> {<br>
> struct weston_desktop_surface *dsurface =<br>
> wl_resource_get_user_data(<wbr>resource);<br>
> - struct weston_desktop_xdg_surface *surface =<br>
> - weston_desktop_surface_get_<wbr>implementation_data(dsurface);<br>
> + struct weston_desktop_xdg_surface *surface;<br>
> +<br>
> + if (!dsurface)<br>
> + return;<br>
> +<br>
> + surface = weston_desktop_surface_get_<wbr>implementation_data(dsurface);<br>
><br>
> if (!weston_desktop_xdg_surface_<wbr>check_role(surface))<br>
> return;<br>
> @@ -1014,8 +1071,12 @@ weston_desktop_xdg_surface_<wbr>protocol_ack_configure(struct wl_client *wl_client,<br>
> {<br>
> struct weston_desktop_surface *dsurface =<br>
> wl_resource_get_user_data(<wbr>resource);<br>
> - struct weston_desktop_xdg_surface *surface =<br>
> - weston_desktop_surface_get_<wbr>implementation_data(dsurface);<br>
> + struct weston_desktop_xdg_surface *surface;<br>
> +<br>
> + if (!dsurface)<br>
> + return;<br>
> +<br>
> + surface = weston_desktop_surface_get_<wbr>implementation_data(dsurface);<br>
><br>
> if (!weston_desktop_xdg_surface_<wbr>check_role(surface))<br>
> return;<br>
<br>
</div></div></blockquote></div><br></div>