GNOME Bugzilla – Bug 759323
gdk_display_get_pointer(): segfault if application client (core) pointer is graphics tablet
Last modified: 2015-12-14 23:15:51 UTC
With GDK 3.18.5, calling gdk_display_get_pointer() when the core pointer for an application is a Wacom graphics tablet causes a segfault. I realize this function is deprecated, but this bug will kill old code using the now-deprecated function. Affects downstream, though we now have workarounds: https://github.com/mypaint/mypaint/issues/526 https://github.com/mypaint/mypaint/issues/513 Problem seems to have arisen with recent stable GDK. Not reproduced with: touchscreen device, touchpad. ---------------------------------------------------------------------- $ xinput list ⎡ Virtual core pointer id=2 [master pointer (3)] ⎜ ↳ Virtual core XTEST pointer id=4 [slave pointer (2)] ⎜ ↳ SYNAPTICS Synaptics Large Touch Screen id=9 [slave pointer (2)] ⎜ ↳ DLL060A:00 06CB:2734 id=11 [slave pointer (2)] ⎜ ↳ Wacom Intuos5 touch M (WL) Pen stylus id=14 [slave pointer (2)] ⎜ ↳ Wacom Intuos5 touch M (WL) Pen eraser id=15 [slave pointer (2)] ⎜ ↳ Wacom Intuos5 touch M (WL) Pen cursor id=16 [slave pointer (2)] ⎜ ↳ Wacom Intuos5 touch M (WL) Pad pad id=17 [slave pointer (2)] ⎜ ↳ Wacom Intuos5 touch M (WL) Finger id=18 [slave pointer (2)] ⎣ Virtual core keyboard id=3 [master keyboard (2)] ↳ Virtual core XTEST keyboard id=5 [slave keyboard (3)] ↳ Power Button id=6 [slave keyboard (3)] ↳ Video Bus id=7 [slave keyboard (3)] ↳ Power Button id=8 [slave keyboard (3)] ↳ Integrated_Webcam_HD id=10 [slave keyboard (3)] ↳ AT Translated Set 2 keyboard id=12 [slave keyboard (3)] ↳ Dell WMI hotkeys id=13 [slave keyboard (3)] ---------------------------------------------------------------------- #!/usr/bin/env python3 # Demonstrate gdk_display_get_pointer() segfault. # To replicate bug: # 1. plug in Wacom tablet # 2. move pointer around on the root window using tablet stylus # 3. run this script in a terminal *while the pointer is moving* # The last-used device must be a tablet, seemingly. # Continuous motion of the stylus makes it much easier to reproduce. # Downstream: https://github.com/mypaint/mypaint/issues/526 + 513 # Debug: gdb -ex r --args python3 crash.py import gi gi.require_version('Gdk', '3.0') from gi.repository import Gdk if __name__ == '__main__': display = Gdk.Display.get_default() print("display:", display) screen, x, y, mask = display.get_pointer() # segfault expected print("pointer screen:", screen) print("pointer pos:", (x, y)) ---------------------------------------------------------------------- $ gdb -ex r --args python3 crash.py GNU gdb (Debian 7.10-1) 7.10 Copyright (C) 2015 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from python3...Reading symbols from /usr/lib/debug//usr/bin/python3.4m...done. done. Starting program: /usr/bin/python3 crash.py [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". /usr/lib/python3/dist-packages/gi/overrides/Gdk.py:432: Warning: g_object_ref: assertion 'G_IS_OBJECT (object)' failed initialized, argv = Gdk.init_check(sys.argv) display: <gtk.gdk.X11Display object at 0x7fffef96ebd0 (GdkX11Display at 0xc4c000)> Program received signal SIGSEGV, Segmentation fault. _gdk_device_query_state (device=0x0, window=0xc55000 [GdkX11Window], root_window=0x7fffffffd860, child_window=0x0, root_x=0x7fffffffd868, root_y=0x7fffffffd870, win_x=0x0, win_y=0x0, mask=0x7fffffffd85c) at /build/gtk+3.0-bNySRH/gtk+3.0-3.18.5/./gdk/gdkdevice.c:1762 1762 /build/gtk+3.0-bNySRH/gtk+3.0-3.18.5/./gdk/gdkdevice.c: No such file or directory. (gdb) bt
+ Trace 235807
It's perhaps worth noting that the core pointer is accessible from Python code, and can be queried for location reliably. A combination of gdk_display_get_device_manager(), gdk_device_manager_get_client_pointer(), and gdk_device_get_position() (or their Python-GI equivalents) works just fine, and seems to be the recommended replacement. See the patch in https://github.com/mypaint/mypaint/issues/513#issuecomment-163302927 for the workaround deployed in MyPaint. This bug is quite tricky to reproduce due to timing issues. If the pointer is left alone for about a second, even if the last device to update its position was a graphics tablet, the code above will run successfully. Is display->core_pointer not being filled properly when Wacom kit begins driving the core pointer on X11? Some race condition?
This is indeed weird, AFAICT display->core_pointer should always be the Virtual Core Pointer. That said, its detection seems somewhat flaky, it should be set to gdk_device_manager_get_client_pointer() internally.
Created attachment 317203 [details] [review] x11: Use client pointer as default core pointer for gtk+2 API There is no need to fiddle with the master devices list.
Review of attachment 317203 [details] [review]: ok
Attachment 317203 [details] pushed as 3733e53 - x11: Use client pointer as default core pointer for gtk+2 API