After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 783502 - Lockup when using wl_shell_surface::set_transient on same surface
Lockup when using wl_shell_surface::set_transient on same surface
Status: RESOLVED FIXED
Product: mutter
Classification: Core
Component: wayland
3.22.x
Other Linux
: Normal normal
: ---
Assigned To: mutter-maint
mutter-maint
Depends on:
Blocks:
 
 
Reported: 2017-06-07 09:45 UTC by 28872d13
Modified: 2017-06-22 06:51 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Minimal example to trigger lock-up (1.30 KB, text/x-csrc)
2017-06-07 09:45 UTC, 28872d13
  Details
wl-shell: Refuse to make a surface transient to itself (1.17 KB, patch)
2017-06-07 12:16 UTC, Florian Müllner
none Details | Review
window: Include window itself in transient loop check (944 bytes, patch)
2017-06-21 17:56 UTC, Florian Müllner
committed Details | Review

Description 28872d13 2017-06-07 09:45:27 UTC
Created attachment 353301 [details]
Minimal example to trigger lock-up

mutter locks up when using wl_shell_surface::set_transient() to set a surface transient to itself.

I realize that this does not make sense, but still it should not crash the whole desktop.

Minimal test case attached for easy reproduction.

$ gcc `pkg-config --libs --cflags wayland-client` gsh_crash.c
$ ./a.out
(best run it in mutter --nested)

This is the backtrace of the process when locked up for reference (debug symbols are missing, but I think you get the idea):
  • #0 meta_window_foreach_ancestor
  • #1 meta_window_is_ancestor_of_transient
  • #2 meta_window_foreach_transient
  • #3 meta_window_move_resize_internal
  • #4 meta_window_wayland_move_resize
  • #5 xdg_toplevel_role_commit
  • #6 apply_pending_state
  • #7 ffi_call_unix64
  • #8 ffi_call
  • #9 wl_closure_invoke
  • #10 wl_client_connection_data
  • #11 wl_event_loop_dispatch
  • #12 wayland_event_source_dispatch
  • #13 g_main_context_dispatch
  • #14 g_main_context_iterate.isra
  • #15 g_main_loop_run
  • #16 meta_run
  • #17 main

Comment 1 Florian Müllner 2017-06-07 12:16:29 UTC
Created attachment 353318 [details] [review]
wl-shell: Refuse to make a surface transient to itself

While this doesn't make sense, we should still deal with it to
avoid an infinite loop when iterating over a window's transients.
Comment 2 Jonas Ådahl 2017-06-07 12:24:08 UTC
Review of attachment 353318 [details] [review]:

Looks fine. We have a similar kind of check in window.c (check_transient_for_loop()). I wonder if that is enough, or if we actually should check for loops here too. I think we have the same problem in meta-wayland-xdg-shell.c because I see no checking like this there either.
Comment 3 28872d13 2017-06-07 19:06:47 UTC
Can confirm that this fixes the problem for me.

I tried to create a recursion with two surfaces by making them transient to each other, but that was already correctly ignored by some other code, which is good.
Comment 4 Florian Müllner 2017-06-07 19:19:06 UTC
(In reply to Jonas Ådahl from comment #2)
> Looks fine. We have a similar kind of check in window.c
> (check_transient_for_loop()). I wonder if that is enough, or if we actually
> should check for loops here too.

That sounds like a good idea, yes.


> I think we have the same problem in meta-wayland-xdg-shell.c because I 
> see no checking like this there either.

Do you mean in xdg_toplevel_set_parent()? Any error there should be caught by the check in meta_window_set_transient_for() you pointed out. Or are you thinking about the parent_surface of popups?
Comment 5 Jonas Ådahl 2017-06-08 01:45:05 UTC
(In reply to Florian Müllner from comment #4)
> (In reply to Jonas Ådahl from comment #2)
> > Looks fine. We have a similar kind of check in window.c
> > (check_transient_for_loop()). I wonder if that is enough, or if we actually
> > should check for loops here too.
> 
> That sounds like a good idea, yes.
> 
> 
> > I think we have the same problem in meta-wayland-xdg-shell.c because I 
> > see no checking like this there either.
> 
> Do you mean in xdg_toplevel_set_parent()? Any error there should be caught
> by the check in meta_window_set_transient_for() you pointed out. Or are you
> thinking about the parent_surface of popups?

Will it? Doesn't that function only go up the chains, without checking for window == parent? get_popup() might have same issue too maybe, I'd have to test to know, because that state tracking is a bit more complicated.
Comment 6 Florian Müllner 2017-06-21 17:56:22 UTC
Created attachment 354193 [details] [review]
window: Include window itself in transient loop check

While it doesn't make sense to set a window as transient to
itself, out existing check whether making a window transient
doesn't cover it, so it's still possible to create an infinite
loop.


(In reply to Jonas Ådahl from comment #5)
> Will it? Doesn't that function only go up the chains, without checking for
> window == parent?

You are right of course. Actually on second thought, extending that check should be enough to address the issue without duplicating it at all in the window backends ...
Comment 7 Jonas Ådahl 2017-06-22 02:21:13 UTC
Review of attachment 354193 [details] [review]:

lgtm.
Comment 8 Florian Müllner 2017-06-22 06:50:58 UTC
Attachment 354193 [details] pushed as 5f49bda - window: Include window itself in transient loop check