<p dir="ltr">Yeah, this is probably better.<br>
--Jason Ekstrand</p>
<p dir="ltr">Reviewed-By: Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>></p>
<div class="gmail_quote">On Jan 21, 2014 9:02 AM, "Neil Roberts" <<a href="mailto:neil@linux.intel.com">neil@linux.intel.com</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
It looks like the rest of the code assumes that shsurf->children_link<br>
is always a consistent list. For example, shell_surface_set_parent<br>
resets children_link to the empty list after it unlinks a child from<br>
its parent. The destroy_shell_surface code just calls wl_list_remove<br>
which leaves the list node with invalid NULL pointers. Maybe the<br>
simplest way to fix it is just to call shell_surface_set_parent in<br>
that code instead of directly manipulating the list. Here is a patch<br>
to do that.<br>
<br>
Regards,<br>
- Neil<br>
<br>
------- >8 --------------- (use git am --scissors to automatically chop here)<br>
Subject: shell: Use shell_surface_set_parent to unlink children on destroy<br>
<br>
Previously when a shell surface is destroyed it would walk through the<br>
list of child surfaces and directly remove their children_link from<br>
the list. This would leave children_link as an invalid list with just<br>
NULL pointers for prev and next. Other parts of the code such as<br>
shell_surface_set_parent assume that children_link is always in a<br>
consistent state (ie, it is the list of sibling surfaces).<br>
destroy_shell_surface also assumes that it can unconditionally call<br>
wl_list_remove on the children_link of the surface being destroyed to<br>
unlink it from its parent if there is one. However, this crashes if<br>
the child's parent is destroyed first because it would leave the child<br>
with an invalid children_link.<br>
<br>
To fix it this patch makes it call shell_surface_set_parent(..., NULL)<br>
when unlinking the surface's children instead of directly manipulating<br>
the list because that function will reset children_link to an empty<br>
list leaving it in a consistent state.<br>
---<br>
 desktop-shell/shell.c | 6 ++----<br>
 1 file changed, 2 insertions(+), 4 deletions(-)<br>
<br>
diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c<br>
index 2f8e610..e3e2c96 100644<br>
--- a/desktop-shell/shell.c<br>
+++ b/desktop-shell/shell.c<br>
@@ -2914,10 +2914,8 @@ destroy_shell_surface(struct shell_surface *shsurf)<br>
        weston_view_destroy(shsurf->view);<br>
<br>
        wl_list_remove(&shsurf->children_link);<br>
-       wl_list_for_each_safe(child, next, &shsurf->children_list, children_link) {<br>
-               wl_list_remove(&child->children_link);<br>
-               child->parent = NULL;<br>
-       }<br>
+       wl_list_for_each_safe(child, next, &shsurf->children_list, children_link)<br>
+               shell_surface_set_parent(child, NULL);<br>
<br>
        wl_list_remove(&shsurf->link);<br>
        free(shsurf);<br>
--<br>
1.8.4.2<br>
<br>
_______________________________________________<br>
wayland-devel mailing list<br>
<a href="mailto:wayland-devel@lists.freedesktop.org">wayland-devel@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/wayland-devel" target="_blank">http://lists.freedesktop.org/mailman/listinfo/wayland-devel</a><br>
</blockquote></div>