Public bug reported:

GTK4 apps on Xorg segfault in gdk_x11_device_xi2_store_axes when the
touchscreen is touched after any input device was disabled or unplugged
(Ubuntu x11-touch patch dereferences a NULL logical touch device)

Ghostty (a GTK4 terminal, installed from the mkasberg/ghostty-ubuntu PPA) 
segfaulted inside
libgtk-4-1 while I touched the laptop's touchscreen. The crash is entirely 
inside GDK's X11
backend and, specifically, inside code added by Ubuntu's
debian/patches/x11-touch/xi2-Expose-a-logical-touch-device.patch. Ghostty's own 
code is not
involved (its only frame is the GLib main loop), so I am filing against gtk4. 
Every GTK4
application running on Xorg on a machine with a touchscreen is affected.

Environment:

- Ubuntu 26.04.1 LTS (resolute), kernel 7.0.0-30-generic
- libgtk-4-1 4.22.4+ds-0ubuntu0.1 (the x11-touch patches were introduced in 
4.22.1+ds-1)
- xserver-xorg-core 2:21.1.22-1ubuntu1, xserver-xorg-input-libinput 
1.5.0-1build1, libinput10 1.31.1-1ubuntu1.1
- XFCE 4.20 session on Xorg (XDG_SESSION_TYPE=x11)
- Dell laptop with a built-in touchscreen: X device "SAPS2101:00 1FD2:B010", 
XITouchClass mode direct, 10 touch points; GDK classifies it as 
GDK_SOURCE_TOUCHSCREEN
- Crashing application: ghostty 1.3.1~ppa2-resolute1 (any GTK4 app will do; 
baobab reproduces it)

What happened:

1. Ghostty started at 18:40 with the touchscreen attached to the Virtual core 
pointer. At
   startup the patch creates a "logical touch device" named "Virtual core 
pointer touch" for
   the seat (its name string is still present in the core dump).
2. At 19:08 a USB graphics tablet was plugged in and at 19:22 unplugged (kernel 
log). The
   unplug produced XIDeviceDisabled hierarchy events; the patch's 
remove_device() calls
   remove_logical_touch_device(), which unconditionally drops the seat's 
logical touch device
   whatever device was removed. It is only re-created by 
ensure_logical_touch_device() when a
   touchscreen is added or attached, which never happened again.
3. Next morning at 09:45:33 a finger touched the screen over a Ghostty window. 
The X server
   delivered a pointer-emulated XI_Motion (flags = XIPointerEmulated, deviceid 
= 2 "Virtual core
   pointer", sourceid = 12, the touchscreen). The patched XI_Motion case 
replaced `device` with
   the seat's logical touch device, which is NULL, and passed it to 
translate_axes().
   gdk_device_get_n_axes(NULL) logged
   "Gdk: gdk_device_get_n_axes: assertion 'GDK_IS_DEVICE (device)' failed" and 
returned 0,
   then gdk_x11_device_xi2_store_axes(NULL, ...) did g_free(device->last_axes) 
and died with
   SIGSEGV at address 0x88.

Backtrace (full version with the decoded XI event, seat state and device table 
in the
attachment; line numbers are from the Ubuntu source tree, upstream 4.22.4 plus 
debian/patches):

```
#0  gdk_x11_device_xi2_store_axes (device=0x0, axes=0x5d369828ba10, n_axes=0) 
at ../../../gdk/x11/gdkdevice-xi2.c:824
#1  translate_axes (device=device@entry=0x0, x=865.602783203125, 
y=71.981201171875, valuators=valuators@entry=0x5d369949a060, 
surface=0x5d3699557130) at ../../../gdk/x11/gdkdevicemanager-xi2.c:1291
#2  0x00007e1970d28714 in gdk_x11_device_manager_xi2_translate_event 
(translator=<optimized out>, display=0x5d36939a9180, xevent=<optimized out>) at 
../../../gdk/x11/gdkdevicemanager-xi2.c:1890
#3  0x00007e1970d47efe in gdk_event_source_translate_event 
(x11_display=0x5d36939a9180, xevent=0x7fffe58e7f30) at 
../../../gdk/x11/gdkeventsource.c:277
#4  gdk_event_source_xevent (x11_display=0x5d36939a9180, xevent=0x7fffe58e7f30) 
at ../../../gdk/x11/gdkeventsource.c:329
#5  0x00007e19708f522a in _gtk_marshal_BOOLEAN__STRING (...) at 
gtk/gtkmarshalers.c:1607
...
#10 0x00007e1970d49b65 in _gdk_x11_display_queue_events 
(display=0x5d36939a9180) at ../../../gdk/x11/gdkeventsource.c:409
#11 0x00007e1970cfbd13 in gdk_display_get_event (display=0x5d36939a9180) at 
../../../gdk/gdkdisplay.c:535
#15 0x00007e19714073c3 in g_main_context_iteration () from 
/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0
```

Frame 2 locals in the core: device = 0x0, source_device = the touchscreen
(name "SAPS2101:00 1FD2:B010", source GDK_SOURCE_TOUCHSCREEN), ev->evtype = 6 
(XI_Motion),
ev->flags = 0x10000 (XIPointerEmulated). The seat, cast to GdkX11SeatXI2, has
logical_touch = 0x0. The device manager's device list still contains ids 2 to 
24, including the
touchscreen, so the id_table lookups themselves succeeded; only the substituted 
logical touch
device is missing.

Kernel log line:

```
ghostty[10637]: segfault at 88 ip 00007e1970d258b0 sp 00007fffe58e76b0 error 4 
in libgtk-4.so.1.2200.4[5258b0,7e19708d4000+571000]
```

Analysis of debian/patches/x11-touch/xi2-Expose-a-logical-touch-
device.patch:

The XI_Motion case substitutes the logical touch device without checking for 
NULL
(patched file, lines 1880 to 1890):

```c
#ifdef XINPUT_2_2
        if (xev->flags & XIPointerEmulated &&
            gdk_device_get_source (source_device) == GDK_SOURCE_TOUCHSCREEN)
          {
            /* Touch drag&drop */
            GdkSeat *seat = gdk_device_get_seat (device);
            device = gdk_x11_seat_xi2_get_logical_touch (GDK_X11_SEAT_XI2 
(seat));
          }
#endif

        axes = translate_axes (device, ...
```

The XI_TouchBegin/XI_TouchEnd and XI_TouchUpdate cases and get_event_surface() 
do the same
substitution, also without a NULL check, so a touch crashes through whichever 
event arrives
first.

The logical touch device is dropped on any device removal, not only when a 
touchscreen goes
away:

```c
static void
remove_logical_touch_device (GdkX11DeviceManagerXI2 *device_manager,
                             GdkDevice              *associated)
{
  GdkSeat *seat;
  GdkDevice *logical_touch;

  seat = gdk_device_get_seat (associated);
  if (!seat)
    return;

  logical_touch = gdk_x11_seat_xi2_get_logical_touch (GDK_X11_SEAT_XI2 (seat));
  device_manager->devices = g_list_remove (device_manager->devices, 
logical_touch);
  gdk_x11_seat_xi2_set_logical_touch (GDK_X11_SEAT_XI2 (seat), NULL);
}
```

called unconditionally from remove_device():

```c
  if (device)
    {
      remove_logical_touch_device (device_manager, device);
      detach_from_seat (device);
```

while ensure_logical_touch_device() returns early for anything that is
not a touchscreen:

```c
  if (gdk_device_get_source (physical) != GDK_SOURCE_TOUCHSCREEN)
    return;
```

So the sequence "app running with a touchscreen, then any input device (mouse, 
keyboard,
tablet, dock) is disabled or unplugged, then the touchscreen is touched over 
the app's window"
crashes every GTK4 app on Xorg.

Suggested fix:

1. In remove_logical_touch_device(), only drop the logical touch device when 
the removed
   device is a touchscreen, and preferably only when no other touchscreen 
remains attached to
   that seat.
2. At the four substitution sites, keep the logical pointer device when
   gdk_x11_seat_xi2_get_logical_touch() returns NULL (or call 
ensure_logical_touch_device()
   lazily) instead of passing NULL on.

**Steps to reproduce (Xorg session, touchscreen enabled and attached to
the core pointer):**

1. Start a GTK4 app, for example `baobab`, and place its window on the 
touchscreen.
2. Tap inside the window with a finger: no crash (control).
3. Disable or unplug any other input device, for example
   `xinput disable "PS/2 Generic Mouse"` or unplug the USB mouse.
4. Tap inside the window again: the app segfaults in 
gdk_x11_device_xi2_store_axes and
   the journal shows "gdk_device_get_n_axes: assertion 'GDK_IS_DEVICE (device)' 
failed".
5. `xinput disable <touchscreen>` followed by `xinput enable <touchscreen>` 
re-creates the
   logical touch device in running apps and makes touches safe again.

Workaround: disable the touchscreen (`xinput disable "SAPS2101:00 1FD2:B010"`, 
or untick
"Enable this device" for it in XFCE's Mouse and Touchpad settings).

Impact: in a GTK4 terminal like Ghostty, which runs all windows in one 
single-instance
process, the crash also kills every shell and every program running in those 
shells.

ProblemType: Bug
DistroRelease: Ubuntu 26.04
Package: libgtk-4-1 4.22.4+ds-0ubuntu0.1
ProcVersionSignature: Ubuntu 7.0.0-30.30-generic 7.0.12
Uname: Linux 7.0.0-30-generic x86_64
ApportVersion: 2.34.1-0ubuntu0.1
Architecture: amd64
CasperMD5CheckResult: pass
CurrentDesktop: XFCE
Date: Thu Sep  3 11:09:26 2026
InstallationDate: Installed on 2026-06-08 (87 days ago)
InstallationMedia: Xubuntu 26.04 "Resolute Raccoon" - Release amd64 (20260423.1)
SourcePackage: gtk4
UpgradeStatus: No upgrade log present (probably fresh install)

** Affects: gtk4 (Ubuntu)
     Importance: Undecided
         Status: New


** Tags: amd64 apport-bug resolute

** Attachment added: "ghostty-gtk4-crash-backtrace.txt"
   
https://bugs.launchpad.net/bugs/2166322/+attachment/5997206/+files/ghostty-gtk4-crash-backtrace.txt

-- 
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/2166322

Title:
  GTK4 apps on Xorg crash on touchscreen touch after any input device is
  unplugged

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/gtk4/+bug/2166322/+subscriptions


-- 
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs

Reply via email to