GNOME Bugzilla – Bug 698248
race in placement for popup-menu/tooltip-window
Last modified: 2014-02-24 17:53:27 UTC
This is a bug I have confirmed in 3.4.4 to 3.8.0 (but might also be in 3.0 and 3.2). It happens when you have fvwm as window manager and more than 4 desktops. Everything works fine in desktops 1-4. But in desktops 5-6 there is a race (probably with window manager) to get the root window geometry via a XLib call. The result is that gibberish is returned for either width or height. This make the popup menu go wild if it is populated with submenus. It may disappear or appear way across the screen. The tooltip window is also affected by the bug, since root window geometry is obtained for tooltip window placement. Here the consequence is that the tooltip may appear in an inappropriate position, like off screen. The problem is definitely *not* present with gtk+2 (2.20 and above), which leads me to believe it is a gtk+3 bug. Seems like a problem with threads calling XLib functions without protection, as Xlib is not thread safe (being asyncronous as it is). My guess is that gtk is racing the window manager for a X property. Probably much too often (I mean, how often does the root window geometry change?) I don't have a simple example, but if you are interested in reproducing the bug, compile rodent filemanager ("emerge x11-misc/rodent" in Gentoo) and test the popup in fvwm in desktops 5 and beyond. Fvwm does not use gtk+ so I believe an incorrect gtk+ usage in fvwm is unlikely. Since the bug is not present in gtk+2, the workaround is to use gtk+2.
This is the information gtk spews out when the race collision occurs: (rodent-desk:2858): Gtk-CRITICAL **: gtk_widget_get_preferred_width_for_height: assertion `height >= 0' failed (rodent-desk:2858): Gtk-CRITICAL **: gtk_widget_get_preferred_width_for_height: assertion `height >= 0' failed (rodent-desk:2858): Gtk-WARNING **: gtk_widget_size_allocate(): attempt to allocate widget with width 325 and height -23 (rodent-desk:2858): Gtk-CRITICAL **: gtk_widget_get_preferred_width_for_height: assertion `height >= 0' failed (rodent-desk:2858): Gtk-CRITICAL **: gtk_widget_get_preferred_width_for_height: assertion `height >= 0' failed (rodent-desk:2858): Gtk-WARNING **: gtk_widget_size_allocate(): attempt to allocate widget with width 325 and height -23
Additional information. This is what valgrind detects when the bug is triggered and which seems to involve a race involving XGetProperty. Xlib is not thread safe, so there might be a thread involved. As far as I can recall, the problem does not occur on single core systems (but I will recheck this if there is any interest in fixing the bug). ==23820== Memcheck, a memory error detector ==23820== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al. ==23820== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info ==23820== Command: rodent-fgr ==23820== --23820-- WARNING: Serious error when reading debug info --23820-- When reading debug info from /usr/lib/opengl/xorg-x11/lib/libGL.so.1.2.0: --23820-- Can't make sense of .got section mapping --23820-- WARNING: Serious error when reading debug info --23820-- When reading debug info from /usr/lib/libglapi.so.0.0.0: --23820-- Can't make sense of .got section mapping get_module_info: module /usr/local/lib/rfm/modules/libfgr.so successfully loaded get_module_info: module /usr/local/lib/rfm/modules/libicons.so successfully loaded get_module_info: module /usr/local/lib/rfm/modules/libcombobox.so successfully loaded ==23820== Invalid read of size 4 ==23820== at 0x465BF99: gdk_x11_screen_get_monitor_workarea (in /usr/lib/libgdk-3.so.0.400.4) ==23820== by 0x4633B1A: gdk_screen_get_monitor_workarea (in /usr/lib/libgdk-3.so.0.400.4) ==23820== by 0x4477142: gtk_tooltip_show_tooltip (in /usr/lib/libgtk-3.so.0.400.4) ==23820== by 0x4477D5B: tooltip_popup_timeout (in /usr/lib/libgtk-3.so.0.400.4) ==23820== by 0x462382C: gdk_threads_dispatch (in /usr/lib/libgdk-3.so.0.400.4) ==23820== by 0x499A47B: ??? (in /usr/lib/libglib-2.0.so.0.3200.4) ==23820== by 0x4999772: g_main_context_dispatch (in /usr/lib/libglib-2.0.so.0.3200.4) ==23820== by 0x4999B07: ??? (in /usr/lib/libglib-2.0.so.0.3200.4) ==23820== by 0x4999F6A: g_main_loop_run (in /usr/lib/libglib-2.0.so.0.3200.4) ==23820== by 0x437B27C: gtk_main (in /usr/lib/libgtk-3.so.0.400.4) ==23820== by 0x572728C: do_find_standalone (find-module.c:239) ==23820== by 0x4071F91: rfm_natural (primary-modules.c:361) ==23820== Address 0x6ef8524 is 3 bytes after a block of size 65 alloc'd ==23820== at 0x4029548: malloc (vg_replace_malloc.c:263) ==23820== by 0x40EE8D0: XGetWindowProperty (in /usr/lib/libX11.so.6.3.0) ==23820== by 0x465BE84: gdk_x11_screen_get_monitor_workarea (in /usr/lib/libgdk-3.so.0.400.4) ==23820== by 0x4633B1A: gdk_screen_get_monitor_workarea (in /usr/lib/libgdk-3.so.0.400.4) ==23820== by 0x4477142: gtk_tooltip_show_tooltip (in /usr/lib/libgtk-3.so.0.400.4) ==23820== by 0x4477D5B: tooltip_popup_timeout (in /usr/lib/libgtk-3.so.0.400.4) ==23820== by 0x462382C: gdk_threads_dispatch (in /usr/lib/libgdk-3.so.0.400.4) ==23820== by 0x499A47B: ??? (in /usr/lib/libglib-2.0.so.0.3200.4) ==23820== by 0x4999772: g_main_context_dispatch (in /usr/lib/libglib-2.0.so.0.3200.4) ==23820== by 0x4999B07: ??? (in /usr/lib/libglib-2.0.so.0.3200.4) ==23820== by 0x4999F6A: g_main_loop_run (in /usr/lib/libglib-2.0.so.0.3200.4) ==23820== by 0x437B27C: gtk_main (in /usr/lib/libgtk-3.so.0.400.4)
Created attachment 265320 [details] [review] Correction for ewmh workaround in gdkscreen-x11.c I have identified the problem and constructed and tested code to fix the bug. In gdkscreen-x11.c there is a "workaround" for ewmh which does not work around correctly. In particular it fails whenever the number of desktops is not a power of 2. One of the "workaround" tests is not entirely good: num % 4 != 0 This is because ewmh stores property in powers of 2, not in the actual number of desktops. The correct way is to perform the test is to examine the _NET_NUMBER_OF_DESKTOPS property and verify if *that* is a multiple of 4. Also, the maximum number of desktops is 256, not 32 as implied by th current gdk code. Please apply the attached patch for 3.8.8. Without patch, popup menus are broken with ewmh when number of desktops is not a power of 2. regards.
Thanks for looking into this, but the analysis seems wrong. Threads are not involved - gtk only makes X calls from the main thread. And there is no limitation to 32 desktops in the gdk code. I just tested gtk with 5 workspaces in gnome-shell, so power-of-2 is not involved. Seems equally likely that fvwm gets something wrong when setting the workarea property. I'll try to reproduce
This is pretty clearly a bug in fvwm. It doesn't seem to update the _NET_WORKAREA property to contain a rectangle for every desktop between 0 and _NET_NUMBER_OF_DESKTOPS - 1. After launching a terminal on desktop 5, I see _NET_NUMBER_OF_DESKTOPS go up to 5, but _NET_WORKAREA still only contains 4 rectangles. I'll commit a simple workaround to deal with this more gracefully.
I've verified your workaround committed to git repository and it works fine. Thanks a bunch!
(Just for reference, while automatic setting of the number of desks indeed seems broken in FVWM, you can also set it manually, using for example "EwmhNumberOfDesktops 8 8", for precisely 8 desks, in your FVWM config file... I set it and restarted FVWM, and now "_NET_WORKAREA" properly contains data for eight desks, instead of the default of four it contained just before, and I don't seem to have menu position issues in QuodLibet and Liferea anymore...).