Public bug reported:

Expected: a GTK 3 application keeps running when an AT-SPI client exits while I 
type.
Happened: the application segfaults in libgtk-3.

LibreOffice Writer crashed while I was typing. A script that uses
pyatspi had exited a few seconds before. I reproduced the crash four
more times in an isolated session. Each time it is a SIGSEGV in the same
loop in libgtk-3.

== Versions ==

- Linux Mint 22.3 (lsb_release -rd: "Linux Mint 22.3", "22.3"), based on Ubuntu 
24.04 noble
- libgtk-3-0t64 3.24.41-4ubuntu1.3, installed from noble-updates/main 
(apt-cache policy)
- libatk-bridge2.0-0t64 and libatspi2.0-0t64 2.52.0-1build1
- libreoffice-core 4:24.2.7-0ubuntu0.24.04.7 (gtk3 VCL plugin)
- python3-pyatspi 2.46.1-1

== Where it crashes ==

The loop in _gtk_accessibility_key_snooper,
gtk/a11y/gtkaccessibilityutil.c:

  150   for (l = key_listener_list; l; l = l->next)
  151     {
  152       KeyEventListener *listener = l->data;
  153
  154       result |= listener->func (&atk_event, listener->data);
  155     }

The faults, resolved with libgtk-3-0t64-dbgsym for this build:

  run A   gtk_main_do_event+3494   mov 0x8(%rax),%rsi   line 154   (registers 
not recorded)
  run B   gtk_main_do_event+3488   mov (%r15),%rax      line 152   r15 = 
0xf546c34db4191dde
  run C   gtk_main_do_event+3494   mov 0x8(%rax),%rsi   line 154   rax = 0
  run D   gtk_main_do_event+3488   mov (%r15),%rax      line 152   r15 = 
0x452dc94eb9d2c550

== What happens just before ==

In runs B, C and D gdb had a breakpoint on
atk_remove_key_event_listener. The last hit before the crash comes from
inside the loop:

  #0  atk_remove_key_event_listener ()        libatk-1.0.so.0
  #1  spi_atk_deregister_event_listeners ()   libatk-bridge-2.0.so.0
  #2  ??? ()                                  libatk-bridge-2.0.so.0
  #3  dbus_connection_dispatch ()             libdbus-1.so.3
  #4  ??? ()                                  libatspi.so.0
  #5  ??? ()                                  libglib-2.0.so.0
  #6  ??? ()                                  libglib-2.0.so.0
  #7  g_main_loop_run ()                      libglib-2.0.so.0
  #8  ??? ()                                  libatk-bridge-2.0.so.0
  #9  gtk_main_do_event ()                    libgtk-3.so.0

Frame 9 returns to gtk_main_do_event+3500, which is mov 0x8(%r15),%r15,
the l = l->next of line 150. So the listener called on line 154 is
removed while it is still running. In atk-adaptor the key listener waits
for the registry in a nested main loop (send_and_allow_reentry,
event.c), and the exit of the last client is handled there
(spi_atk_remove_client, bridge.c).

In run D I also logged the node passed to g_slist_delete_link during
that removal and what GTK reads at +3500 afterwards:

  FREE link=0x5601199717a0
  INCR r15=0x5601199717a0 next=0x452dc94eb9d2c550
  SIGSEGV at +3488, r15 = r11 = 0x452dc94eb9d2c550

Every frame in every trace is on thread 1.

== How I reproduced it ==

Xephyr with a private D-Bus session and its own accessibility bus.
LibreOffice Writer runs under gdb with a short document open, xdotool
types into it, and a shell loop keeps starting this and letting it exit:

  python3 -c "import pyatspi; print([a.name for a in
pyatspi.Registry.getDesktop(0)])"

- Run A, 70 ms per key and one probe every 5 s. SIGSEGV after the second probe. 
Two more 90 s runs with these settings did not crash.
- Run B, 6 ms per key and probes 0.2 s apart. SIGSEGV after 39 probes.
- Runs C and D, 6 ms per key and probes 0.7 s apart. SIGSEGV after 43 probes 
and after 2 probes.

Typing without probes did not crash in 90 s, and neither did probes
without typing.

Most removals from inside the loop are harmless. In runs B and C, 30 of
38 and 37 of 42 removals came from inside gtk_main_do_event, and each
run crashed once. With MALLOC_PERTURB_=165 set for LibreOffice the
packaged library crashed at the first such removal in three of three
runs, with r15 = 0xa5a5a5a5a5a5a5a5.

With a minimal Python GTK 3 window (one GtkTextView) in place of
LibreOffice, the removal came from inside gtk_main_do_event 5 times in
500 probes and nothing crashed.

== With the upstream commit ==

I built the noble source (3.24.41-4ubuntu1.3 with Ubuntu's patches)
twice, as is and with commit e6372d29 on top, and ran LibreOffice
against each build through LD_LIBRARY_PATH. Settings as in runs C and D.

- rebuilt, unpatched, MALLOC_PERTURB_=165, 3 runs: SIGSEGV at the first or 
second removal from inside the loop
- rebuilt, with e6372d29, MALLOC_PERTURB_=165, 2 runs: no crash in 300 probes 
each, with 246 and 245 removals from inside the loop
- rebuilt, with e6372d29, MALLOC_PERTURB_ not set, 1 run: no crash in 300 
probes, with 246 removals from inside the loop

These were plain meson builds and not package builds (no introspection,
file print backend only, no hardening flags).

== Upstream ==

The loop was changed on the gtk-3-24 branch on 2026-10-01 in commit
e6372d29, "a11y: Browse key listener list safely" (merge request 10391,
https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/10391). Its message
shows a backtrace through the same function and links a report from
xfce4-screensaver. No release has the commit yet, the latest being
3.24.52, and no Ubuntu series ships it.

Could this be considered for noble?

I can attach the full gdb logs and the scripts, and I am happy to run
more tests.

** Affects: gtk+3.0 (Ubuntu)
     Importance: Undecided
         Status: New

** Description changed:

+ Expected: a GTK 3 application keeps running when an AT-SPI client exits while 
I type.
+ Happened: the application segfaults in libgtk-3.
+ 
  LibreOffice Writer crashed while I was typing. A script that uses
  pyatspi had exited a few seconds before. I reproduced the crash four
  more times in an isolated session. Each time it is a SIGSEGV in the same
  loop in libgtk-3.
  
  == Versions ==
  
- - Linux Mint 22.3, which takes these packages from Ubuntu noble
- - libgtk-3-0t64 3.24.41-4ubuntu1.3
+ - Linux Mint 22.3 (lsb_release -rd: "Linux Mint 22.3", "22.3"), based on 
Ubuntu 24.04 noble
+ - libgtk-3-0t64 3.24.41-4ubuntu1.3, installed from noble-updates/main 
(apt-cache policy)
  - libatk-bridge2.0-0t64 and libatspi2.0-0t64 2.52.0-1build1
  - libreoffice-core 4:24.2.7-0ubuntu0.24.04.7 (gtk3 VCL plugin)
  - python3-pyatspi 2.46.1-1
  
  == Where it crashes ==
  
  The loop in _gtk_accessibility_key_snooper,
  gtk/a11y/gtkaccessibilityutil.c:
  
    150   for (l = key_listener_list; l; l = l->next)
    151     {
    152       KeyEventListener *listener = l->data;
    153
    154       result |= listener->func (&atk_event, listener->data);
    155     }
  
  The faults, resolved with libgtk-3-0t64-dbgsym for this build:
  
    run A   gtk_main_do_event+3494   mov 0x8(%rax),%rsi   line 154   (registers 
not recorded)
    run B   gtk_main_do_event+3488   mov (%r15),%rax      line 152   r15 = 
0xf546c34db4191dde
    run C   gtk_main_do_event+3494   mov 0x8(%rax),%rsi   line 154   rax = 0
    run D   gtk_main_do_event+3488   mov (%r15),%rax      line 152   r15 = 
0x452dc94eb9d2c550
  
  == What happens just before ==
  
  In runs B, C and D gdb had a breakpoint on
  atk_remove_key_event_listener. The last hit before the crash comes from
  inside the loop:
  
    #0  atk_remove_key_event_listener ()        libatk-1.0.so.0
    #1  spi_atk_deregister_event_listeners ()   libatk-bridge-2.0.so.0
    #2  ??? ()                                  libatk-bridge-2.0.so.0
    #3  dbus_connection_dispatch ()             libdbus-1.so.3
    #4  ??? ()                                  libatspi.so.0
    #5  ??? ()                                  libglib-2.0.so.0
    #6  ??? ()                                  libglib-2.0.so.0
    #7  g_main_loop_run ()                      libglib-2.0.so.0
    #8  ??? ()                                  libatk-bridge-2.0.so.0
    #9  gtk_main_do_event ()                    libgtk-3.so.0
  
  Frame 9 returns to gtk_main_do_event+3500, which is mov 0x8(%r15),%r15,
  the l = l->next of line 150. So the listener called on line 154 is
  removed while it is still running. In atk-adaptor the key listener waits
  for the registry in a nested main loop (send_and_allow_reentry,
  event.c), and the exit of the last client is handled there
  (spi_atk_remove_client, bridge.c).
  
  In run D I also logged the node passed to g_slist_delete_link during
  that removal and what GTK reads at +3500 afterwards:
  
    FREE link=0x5601199717a0
    INCR r15=0x5601199717a0 next=0x452dc94eb9d2c550
    SIGSEGV at +3488, r15 = r11 = 0x452dc94eb9d2c550
  
  Every frame in every trace is on thread 1.
  
  == How I reproduced it ==
  
  Xephyr with a private D-Bus session and its own accessibility bus.
  LibreOffice Writer runs under gdb with a short document open, xdotool
  types into it, and a shell loop keeps starting this and letting it exit:
  
    python3 -c "import pyatspi; print([a.name for a in
  pyatspi.Registry.getDesktop(0)])"
  
  - Run A, 70 ms per key and one probe every 5 s. SIGSEGV after the second 
probe. Two more 90 s runs with these settings did not crash.
  - Run B, 6 ms per key and probes 0.2 s apart. SIGSEGV after 39 probes.
  - Runs C and D, 6 ms per key and probes 0.7 s apart. SIGSEGV after 43 probes 
and after 2 probes.
  
  Typing without probes did not crash in 90 s, and neither did probes
  without typing.
  
  Most removals from inside the loop are harmless. In runs B and C, 30 of
  38 and 37 of 42 removals came from inside gtk_main_do_event, and each
  run crashed once. With MALLOC_PERTURB_=165 set for LibreOffice the
  packaged library crashed at the first such removal in three of three
  runs, with r15 = 0xa5a5a5a5a5a5a5a5.
  
  With a minimal Python GTK 3 window (one GtkTextView) in place of
  LibreOffice, the removal came from inside gtk_main_do_event 5 times in
  500 probes and nothing crashed.
  
  == With the upstream commit ==
  
  I built the noble source (3.24.41-4ubuntu1.3 with Ubuntu's patches)
  twice, as is and with commit e6372d29 on top, and ran LibreOffice
  against each build through LD_LIBRARY_PATH. Settings as in runs C and D.
  
  - rebuilt, unpatched, MALLOC_PERTURB_=165, 3 runs: SIGSEGV at the first or 
second removal from inside the loop
  - rebuilt, with e6372d29, MALLOC_PERTURB_=165, 2 runs: no crash in 300 probes 
each, with 246 and 245 removals from inside the loop
  - rebuilt, with e6372d29, MALLOC_PERTURB_ not set, 1 run: no crash in 300 
probes, with 246 removals from inside the loop
  
  These were plain meson builds and not package builds (no introspection,
  file print backend only, no hardening flags).
  
  == Upstream ==
  
  The loop was changed on the gtk-3-24 branch on 2026-10-01 in commit
  e6372d29, "a11y: Browse key listener list safely" (merge request 10391,
  https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/10391). Its message
  shows a backtrace through the same function and links a report from
  xfce4-screensaver. No release has the commit yet, the latest being
  3.24.52, and no Ubuntu series ships it.
  
  Could this be considered for noble?
  
  I can attach the full gdb logs and the scripts, and I am happy to run
  more tests.

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

Title:
  Segfault in _gtk_accessibility_key_snooper when the last AT-SPI client
  exits during a key press (noble, 3.24.41-4ubuntu1.3)

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/gtk+3.0/+bug/2169718/+subscriptions


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

Reply via email to