[weston,1/1] desktop-shell: detect stale shell surface outputs

Submitted by Fabien Lahoudere on May 2, 2018, 9:10 a.m.

Details

Message ID 1525252232-5454-1-git-send-email-fabien.lahoudere@collabora.com
State Accepted
Commit 99f8c085594dba25006fa29fbfb09b60105bbaf9
Headers show
Series "Series without cover letter" ( rev: 1 ) in Wayland

Not browsing as part of any series.

Commit Message

Fabien Lahoudere May 2, 2018, 9:10 a.m.
From: Semi Malinen <semi.malinen@ge.com>

When displays are hot (un)plugged, it may happen that
a shell surface is left with a stale pointer to an output
that has already been freed. Add an output destroy listener
to catch such situations and set the output pointer to NULL.

Signed-off-by: Semi Malinen <semi.malinen@ge.com>
Signed-off-by: Fabien Lahoudere <fabien.lahoudere@collabora.com>
---
 desktop-shell/shell.c | 29 +++++++++++++++++++++++++++--
 1 file changed, 27 insertions(+), 2 deletions(-)

Patch hide | download patch | download mbox

diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index b846e30..b539431 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -128,6 +128,7 @@  struct shell_surface {
 
 	struct weston_output *fullscreen_output;
 	struct weston_output *output;
+	struct wl_listener output_destroy_listener;
 
 	struct surface_state {
 		bool fullscreen;
@@ -1934,6 +1935,17 @@  shell_surface_update_layer(struct shell_surface *shsurf)
 }
 
 static void
+notify_output_destroy(struct wl_listener *listener, void *data)
+{
+	struct shell_surface *shsurf =
+		container_of(listener,
+			     struct shell_surface, output_destroy_listener);
+
+	shsurf->output = NULL;
+	shsurf->output_destroy_listener.notify = NULL;
+}
+
+static void
 shell_surface_set_output(struct shell_surface *shsurf,
                          struct weston_output *output)
 {
@@ -1948,6 +1960,18 @@  shell_surface_set_output(struct shell_surface *shsurf,
 		shsurf->output = es->output;
 	else
 		shsurf->output = get_default_output(es->compositor);
+
+	if (shsurf->output_destroy_listener.notify) {
+		wl_list_remove(&shsurf->output_destroy_listener.link);
+		shsurf->output_destroy_listener.notify = NULL;
+	}
+
+	if (!shsurf->output)
+		return;
+
+	shsurf->output_destroy_listener.notify = notify_output_destroy;
+	wl_signal_add(&shsurf->output->destroy_signal,
+		      &shsurf->output_destroy_listener);
 }
 
 static void
@@ -1986,7 +2010,7 @@  unset_maximized(struct shell_surface *shsurf)
 		weston_desktop_surface_get_surface(shsurf->desktop_surface);
 
 	/* undo all maximized things here */
-	shsurf->output = get_default_output(surface->compositor);
+	shell_surface_set_output(shsurf, get_default_output(surface->compositor));
 
 	if (shsurf->saved_position_valid)
 		weston_view_set_position(shsurf->view,
@@ -2348,7 +2372,8 @@  desktop_surface_added(struct weston_desktop_surface *desktop_surface,
 	shsurf->fullscreen.black_view = NULL;
 	wl_list_init(&shsurf->fullscreen.transform.link);
 
-	shsurf->output = get_default_output(shsurf->shell->compositor);
+	shell_surface_set_output(
+		shsurf, get_default_output(shsurf->shell->compositor));
 
 	wl_signal_init(&shsurf->destroy_signal);
 

Comments

On Wed,  2 May 2018 11:10:32 +0200
Fabien Lahoudere <fabien.lahoudere@collabora.com> wrote:

> From: Semi Malinen <semi.malinen@ge.com>
> 
> When displays are hot (un)plugged, it may happen that
> a shell surface is left with a stale pointer to an output
> that has already been freed. Add an output destroy listener
> to catch such situations and set the output pointer to NULL.
> 
> Signed-off-by: Semi Malinen <semi.malinen@ge.com>
> Signed-off-by: Fabien Lahoudere <fabien.lahoudere@collabora.com>
> ---
>  desktop-shell/shell.c | 29 +++++++++++++++++++++++++++--
>  1 file changed, 27 insertions(+), 2 deletions(-)

Pushed with my R-b:
   e7a52fbb..99f8c085  master -> master


Thanks,
pq