Skip to content

Fix crash with almost mapped Wayland windows during hotplugs

Jonas Ådahl requested to merge jadahl/mutter:wip/window-hotplug-tests into main

The main commits describes it as this:

If the window didn't have a size, it would still have a monitor, and
when we are asked to update, we must update, as the old monitor might
not be kept around, leaving us vulnerable to use after free.

Avoid not updating the monitor by using the stored IDs (preferred, or
previous) to find suitable logical monitors, with the primary monitor
being the last fallback unless we're completely headless.

This fixes the assert

  !window->monitor ||
  g_list_find (meta_monitor_manager_get_logical_monitors (monitor_manager),
               window->monitor)

in meta_window_update_for_monitors_changed() being hit when a Wayland
window has been created, but not mapped, when a hotplug happens.

and fixes the following crash:

#0  0x00007ffff755fafc in __pthread_kill_implementation () from /lib64/libc.so.6
#1  0x00007ffff75132a6 in raise () from /lib64/libc.so.6
#2  0x00007ffff74e67f3 in abort () from /lib64/libc.so.6
#3  0x00007ffff7845d8c in g_assertion_message (domain=<optimized out>, file=<optimized out>, line=<optimized out>, func=0x7ffff7f06760 <__func__.34> "meta_window_update_for_monitors_changed", message=<optimized out>) at ../glib/gtestutils.c:3246
#4  0x00007ffff78a2a6b in g_assertion_message_expr (domain=0x7ffff7f04366 "libmutter", file=0x7ffff7f04314 "../src/core/window.c", line=3745, func=0x7ffff7f06760 <__func__.34> "meta_window_update_for_monitors_changed", expr=<optimized out>) at ../glib/gtestutils.c:3272
#5  0x00007ffff7defd5b in meta_window_update_for_monitors_changed (window=0x671320) at ../src/core/window.c:3745
#6  0x00007ffff7899758 in g_slist_foreach (list=<optimized out>, func=0x7ffff7def992 <meta_window_update_for_monitors_changed>, user_data=0x0) at ../glib/gslist.c:885
#7  0x00007ffff7dbe562 in meta_display_foreach_window (display=0x6b9c00, flags=META_LIST_INCLUDE_OVERRIDE_REDIRECT, func=0x7ffff7def992 <meta_window_update_for_monitors_changed>, data=0x0) at ../src/core/display.c:3185
#8  0x00007ffff7dbe5fd in on_monitors_changed_internal (monitor_manager=0x49de30, display=0x6b9c00) at ../src/core/display.c:3210
#9  0x00007ffff796f4ff in g_closure_invoke (closure=0x6d5740, return_value=return_value@entry=0x0, n_param_values=1, param_values=param_values@entry=0x7fffffffc2a0, invocation_hint=invocation_hint@entry=0x7fffffffc240) at ../gobject/gclosure.c:830
#10 0x00007ffff7981316 in signal_emit_unlocked_R (node=node@entry=0x44b700, detail=detail@entry=0, instance=instance@entry=0x49de30, emission_return=emission_return@entry=0x0, instance_and_params=instance_and_params@entry=0x7fffffffc2a0) at ../gobject/gsignal.c:3740
#11 0x00007ffff7987699 in g_signal_emit_valist (instance=<optimized out>, signal_id=<optimized out>, detail=<optimized out>, var_args=var_args@entry=0x7fffffffc418) at ../gobject/gsignal.c:3495
#12 0x00007ffff7987bc2 in g_signal_emit (instance=<optimized out>, signal_id=<optimized out>, detail=<optimized out>) at ../gobject/gsignal.c:3551
#13 0x00007ffff7d89915 in meta_monitor_manager_notify_monitors_changed (manager=0x49de30) at ../src/backends/meta-monitor-manager.c:3517
#14 0x00007ffff7d89b2f in meta_monitor_manager_rebuild (manager=0x49de30, config=0x739140) at ../src/backends/meta-monitor-manager.c:3603
#15 0x00007ffff7eb872b in meta_monitor_manager_native_apply_monitors_config (manager=0x49de30, config=0x739140, method=META_MONITORS_CONFIG_METHOD_PERSISTENT, error=0x7fffffffc5f8) at ../src/backends/native/meta-monitor-manager-native.c:348
#16 0x00007ffff7d83ebf in meta_monitor_manager_apply_monitors_config (manager=0x49de30, config=0x739140, method=META_MONITORS_CONFIG_METHOD_PERSISTENT, error=0x7fffffffc5f8) at ../src/backends/meta-monitor-manager.c:635
#17 0x00007ffff7d8446d in meta_monitor_manager_ensure_configured (manager=0x49de30) at ../src/backends/meta-monitor-manager.c:818
#18 0x00007ffff7d89c7b in meta_monitor_manager_reconfigure (manager=0x49de30) at ../src/backends/meta-monitor-manager.c:3661
#19 0x00007ffff7d89ca2 in meta_monitor_manager_reload (manager=0x49de30) at ../src/backends/meta-monitor-manager.c:3668
#20 0x00000000004067bd in test_case_do (test=0x713f20, argc=4, argv=0x6e7920, error=0x7fffffffc990) at ../src/tests/test-runner.c:1012
#21 0x0000000000406b36 in run_test (context=0x415430, filename=0x430200 "/home/jonas/Dev/gnome/mutter/build/../src/tests/stacking/monitor-changes.metatest", index=1) at ../src/tests/test-runner.c:1110
#22 0x0000000000406d9d in run_tests (context=0x415430, info=0x7fffffffd110) at ../src/tests/test-runner.c:1191
#23 0x00007ffff5f4dc04 in ffi_call_unix64 () from /lib64/libffi.so.6
#24 0x00007ffff5f4d108 in ffi_call () from /lib64/libffi.so.6
#25 0x00007ffff797024d in g_cclosure_marshal_generic_va (closure=closure@entry=0x431c20, return_value=return_value@entry=0x7fffffffcd90, instance=<optimized out>, instance@entry=0x415430, args_list=args_list@entry=0x7fffffffce68, marshal_data=marshal_data@entry=0x0, n_params=n_params@entry=0, param_types=0x0) at ../gobject/gclosure.c:1648
#26 0x00007ffff796f729 in _g_closure_invoke_va (closure=closure@entry=0x431c20, return_value=return_value@entry=0x7fffffffcd90, instance=instance@entry=0x415430, args=args@entry=0x7fffffffce68, n_params=0, param_types=0x0) at ../gobject/gclosure.c:893
#27 0x00007ffff7987a26 in g_signal_emit_valist (instance=0x415430, signal_id=<optimized out>, detail=<optimized out>, var_args=var_args@entry=0x7fffffffce68) at ../gobject/gsignal.c:3405
#28 0x00007ffff7987bc2 in g_signal_emit (instance=<optimized out>, signal_id=<optimized out>, detail=<optimized out>) at ../gobject/gsignal.c:3551
#29 0x00007ffff7fad13c in run_tests_idle (user_data=0x415430) at ../src/tests/meta-context-test.c:221
#30 0x00007ffff787a7e4 in g_main_dispatch (context=0x4af0e0) at ../glib/gmain.c:3413
#31 g_main_context_dispatch (context=0x4af0e0) at ../glib/gmain.c:4131
#32 0x00007ffff787ab48 in g_main_context_iterate (context=0x4af0e0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at ../glib/gmain.c:4207
#33 0x00007ffff787ae23 in g_main_loop_run (loop=0x667ca0) at ../glib/gmain.c:4405
#34 0x00007ffff7dd0879 in meta_context_run_main_loop (context=0x415430, error=0x7fffffffd0c0) at ../src/core/meta-context.c:445
#35 0x00007ffff7fad3c1 in meta_context_test_run_tests (context_test=0x415430, flags=META_TEST_RUN_FLAG_NONE) at ../src/tests/meta-context-test.c:283
#36 0x000000000040717a in main (argc=2, argv=0x7fffffffd278) at ../src/tests/test-runner.c:1313

The rest of the commits are mostly about improving the test suite to enable adding a test case that reproduces the crash, as well as some minor cleanups.

Related: https://bugzilla.redhat.com/show_bug.cgi?id=2075818

Merge request reports