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 759323 - gdk_display_get_pointer(): segfault if application client (core) pointer is graphics tablet
gdk_display_get_pointer(): segfault if application client (core) pointer is g...
Status: RESOLVED FIXED
Product: gtk+
Classification: Platform
Component: Class: GdkDevice
3.18.x
Other Linux
: Normal critical
: ---
Assigned To: gtk-bugs
Carlos Garnacho
Depends on:
Blocks:
 
 
Reported: 2015-12-11 02:31 UTC by Andrew Chadwick
Modified: 2015-12-14 23:15 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
x11: Use client pointer as default core pointer for gtk+2 API (2.12 KB, patch)
2015-12-11 12:19 UTC, Carlos Garnacho
committed Details | Review

Description Andrew Chadwick 2015-12-11 02:31:14 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
  • #0 _gdk_device_query_state
    at /build/gtk+3.0-bNySRH/gtk+3.0-3.18.5/./gdk/gdkdevice.c line 1762
  • #1 gdk_display_get_pointer
    at /build/gtk+3.0-bNySRH/gtk+3.0-3.18.5/./gdk/gdkdisplay.c line 578
  • #2 ffi_call_unix64
  • #3 ffi_call
  • #4 pygi_invoke_c_callable
    at ../../gi/pygi-invoke.c line 645
  • #5 pygi_function_cache_invoke
  • #6 pygi_callable_info_invoke
  • #7 _wrap_g_callable_info_invoke
  • #8 _callable_info_call
  • #9 PyObject_Call
    at ../Objects/abstract.c line 2040
  • #10 PyEval_EvalFrameEx
    at ../Python/ceval.c line 4466
  • #11 PyEval_EvalFrameEx
    at ../Python/ceval.c line 4264
  • #12 PyEval_EvalFrameEx
  • #13 PyEval_EvalCodeEx
    at ../Python/ceval.c line 3588
  • #14 PyEval_EvalCode
    at ../Python/ceval.c line 775
  • #15 run_mod
  • #16 PyRun_FileExFlags
  • #17 PyRun_SimpleFileExFlags
    at ../Python/pythonrun.c line 1601
  • #18 Py_Main
    at ../Modules/main.c line 319
  • #19 Py_Main
    at ../Modules/main.c line 751
  • #20 main
    at ../Modules/python.c line 69
  • #21 __libc_start_main
    at libc-start.c line 287
  • #22 _start

Comment 1 Andrew Chadwick 2015-12-11 11:10:54 UTC
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?
Comment 2 Carlos Garnacho 2015-12-11 12:19:23 UTC
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.
Comment 3 Carlos Garnacho 2015-12-11 12:19:47 UTC
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.
Comment 4 Matthias Clasen 2015-12-11 12:53:32 UTC
Review of attachment 317203 [details] [review]:

ok
Comment 5 Carlos Garnacho 2015-12-14 23:15:46 UTC
Attachment 317203 [details] pushed as 3733e53 - x11: Use client pointer as default core pointer for gtk+2 API