Skip to content

[GTK3] Jvm crash with SIGSEGV when calling Tree.removeAll() #3329

@om-11-2024

Description

@om-11-2024

Describe the bug
Jvm process crashes with SIGSEGV if there is a Tree with expanded+selected item and Tree.removeAll() is called.

To Reproduce

Here is a snippet for manual reproduction: TreeCrashBug.java.
[a version where clicks emulated in code: TreeCrashBugAuto.java]
Steps to reproduce:

  1. launch the app (preferably with env variables described below)
  2. click and expand node v1_1
  3. click and expand node v1_1_0 (the node becomes selected)
Image
  1. press GO button => the program crashes and prints something like this into console:
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007f2d8349392a, pid=47299, tid=47305
#
# JRE version: OpenJDK Runtime Environment (25.0.2+10) (build 25.0.2+10-Ubuntu-124.04)
# Java VM: OpenJDK 64-Bit Server VM (25.0.2+10-Ubuntu-124.04, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, linux-amd64)
# Problematic frame:
# C  [libgtk-3.so.0+0x49392a]  gtk_tree_store_get_path+0xc9
...

The generated error report file has this stacktrace:

---------------  T H R E A D  ---------------

Current thread (0x00007f2de801b2d0):  JavaThread "main"             [_thread_in_native, id=47305, stack(0x00007f2dee700000,0x00007f2dee800000) (1024K)]

Stack: [0x00007f2dee700000,0x00007f2dee800000],  sp=0x00007f2dee7fc010,  free space=1008k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C  [libgtk-3.so.0+0x49392a]  gtk_tree_store_get_path+0xc9
C  [libgtk-3.so.0+0x493a0c]  gtk_tree_store_get_path+0x1ab
C  [libgtk-3.so.0+0x47c542]  gtk_tree_model_get_path+0x142
C  [libswt-pi3-gtk-4973r12.so+0x48655]  Java_org_eclipse_swt_internal_gtk_GTK_gtk_1tree_1model_1get_1path+0xf
j  org.eclipse.swt.widgets.TreeItem.getParentItem()Lorg/eclipse/swt/widgets/TreeItem;+15
J 1275 c1 org.eclipse.jface.viewers.AbstractTreeViewer.getTreePathFromItem(Lorg/eclipse/swt/widgets/Item;)Lorg/eclipse/jface/viewers/TreePath; (47 bytes) @ 0x00007f2dd07a7f7c [0x00007f2dd07a7800+0x000000000000077c]
j  org.eclipse.jface.viewers.AbstractTreeViewer.internalFindItem(Lorg/eclipse/jface/viewers/TreePath;)Lorg/eclipse/swt/widgets/Widget;+44
j  org.eclipse.jface.viewers.AbstractTreeViewer.internalFindItems(Ljava/lang/Object;)[Lorg/eclipse/swt/widgets/Widget;+14
j  org.eclipse.jface.viewers.TreeViewer.replace(Ljava/lang/Object;ILjava/lang/Object;)V+69
j  treebug.TreeCrashBugAuto$TestContentProvider.updateElement(Lorg/eclipse/jface/viewers/TreePath;I)V+17
j  org.eclipse.jface.viewers.TreeViewer.virtualLazyUpdateWidget(Lorg/eclipse/swt/widgets/Widget;I)V+65
j  org.eclipse.jface.viewers.TreeViewer.lambda$1(Lorg/eclipse/swt/widgets/Event;)V+41
j  org.eclipse.jface.viewers.TreeViewer$$Lambda+0x0000000078097ab0.handleEvent(Lorg/eclipse/swt/widgets/Event;)V+5
j  org.eclipse.swt.widgets.EventTable.sendEvent(Lorg/eclipse/swt/widgets/Event;)V+243
j  org.eclipse.swt.widgets.Display.sendEvent(Lorg/eclipse/swt/widgets/EventTable;Lorg/eclipse/swt/widgets/Event;)V+12
j  org.eclipse.swt.widgets.Widget.sendEvent(Lorg/eclipse/swt/widgets/Event;)V+26
j  org.eclipse.swt.widgets.Widget.sendEvent(ILorg/eclipse/swt/widgets/Event;Z)V+73
j  org.eclipse.swt.widgets.Widget.sendEvent(ILorg/eclipse/swt/widgets/Event;)V+4
j  org.eclipse.swt.widgets.Tree.checkData(Lorg/eclipse/swt/widgets/TreeItem;)Z+112
j  org.eclipse.swt.widgets.Tree.cellDataProc(JJJJJ)J+180
j  org.eclipse.swt.widgets.Display.cellDataProc(JJJJJ)J+25
v  ~StubRoutines::call_stub 0x00007f2dd7b37fa6
V  [libjvm.so+0x9e4d50]  JavaCalls::call_helper(JavaValue*, methodHandle const&, JavaCallArguments*, JavaThread*)+0x2b0
V  [libjvm.so+0xaa1b9b]  jni_invoke_nonstatic(JNIEnv_*, JavaValue*, _jobject*, JNICallType, _jmethodID*, JNI_ArgumentPusher*, JavaThread*) [clone .constprop.1]+0x1db
V  [libjvm.so+0xaaca78]  jni_CallLongMethodV+0x1c8
Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j  org.eclipse.swt.internal.gtk.GTK.gtk_tree_model_get_path(JJ)J+0
j  org.eclipse.swt.widgets.TreeItem.getParentItem()Lorg/eclipse/swt/widgets/TreeItem;+15
J 1275 c1 org.eclipse.jface.viewers.AbstractTreeViewer.getTreePathFromItem(Lorg/eclipse/swt/widgets/Item;)Lorg/eclipse/jface/viewers/TreePath; (47 bytes) @ 0x00007f2dd07a7f7c [0x00007f2dd07a7800+0x000000000000077c]
j  org.eclipse.jface.viewers.AbstractTreeViewer.internalFindItem(Lorg/eclipse/jface/viewers/TreePath;)Lorg/eclipse/swt/widgets/Widget;+44
j  org.eclipse.jface.viewers.AbstractTreeViewer.internalFindItems(Ljava/lang/Object;)[Lorg/eclipse/swt/widgets/Widget;+14
j  org.eclipse.jface.viewers.TreeViewer.replace(Ljava/lang/Object;ILjava/lang/Object;)V+69
j  treebug.TreeCrashBugAuto$TestContentProvider.updateElement(Lorg/eclipse/jface/viewers/TreePath;I)V+17
j  org.eclipse.jface.viewers.TreeViewer.virtualLazyUpdateWidget(Lorg/eclipse/swt/widgets/Widget;I)V+65
j  org.eclipse.jface.viewers.TreeViewer.lambda$1(Lorg/eclipse/swt/widgets/Event;)V+41
j  org.eclipse.jface.viewers.TreeViewer$$Lambda+0x0000000078097ab0.handleEvent(Lorg/eclipse/swt/widgets/Event;)V+5
j  org.eclipse.swt.widgets.EventTable.sendEvent(Lorg/eclipse/swt/widgets/Event;)V+243
j  org.eclipse.swt.widgets.Display.sendEvent(Lorg/eclipse/swt/widgets/EventTable;Lorg/eclipse/swt/widgets/Event;)V+12
j  org.eclipse.swt.widgets.Widget.sendEvent(Lorg/eclipse/swt/widgets/Event;)V+26
j  org.eclipse.swt.widgets.Widget.sendEvent(ILorg/eclipse/swt/widgets/Event;Z)V+73
j  org.eclipse.swt.widgets.Widget.sendEvent(ILorg/eclipse/swt/widgets/Event;)V+4
j  org.eclipse.swt.widgets.Tree.checkData(Lorg/eclipse/swt/widgets/TreeItem;)Z+112
j  org.eclipse.swt.widgets.Tree.cellDataProc(JJJJJ)J+180
j  org.eclipse.swt.widgets.Display.cellDataProc(JJJJJ)J+25
v  ~StubRoutines::call_stub 0x00007f2dd7b37fa6
j  org.eclipse.swt.internal.gtk.GTK.gtk_tree_store_clear(J)V+0
j  org.eclipse.swt.widgets.Tree.removeAll()V+34
j  org.eclipse.jface.viewers.TreeViewer.removeAll(Lorg/eclipse/swt/widgets/Control;)V+4
j  org.eclipse.jface.viewers.AbstractTreeViewer.lambda$2()V+12
j  org.eclipse.jface.viewers.AbstractTreeViewer$$Lambda+0x0000000078098ea8.run()V+4
j  org.eclipse.jface.viewers.StructuredViewer.preservingSelection(Ljava/lang/Runnable;Z)V+26
j  org.eclipse.jface.viewers.TreeViewer.preservingSelection(Ljava/lang/Runnable;Z)V+29
j  org.eclipse.jface.viewers.StructuredViewer.preservingSelection(Ljava/lang/Runnable;)V+3
j  org.eclipse.jface.viewers.AbstractTreeViewer.inputChanged(Ljava/lang/Object;Ljava/lang/Object;)V+7
j  org.eclipse.jface.viewers.ContentViewer.setInput(Ljava/lang/Object;)V+72
j  org.eclipse.jface.viewers.StructuredViewer.setInput(Ljava/lang/Object;)V+33
j  treebug.TreeCrashBugAuto.main([Ljava/lang/String;)V+151
v  ~StubRoutines::call_stub 0x00007f2dd7b37fa6

It's a little strange actually: it contains nested calls to Tree.cellDataProc(...).

I was able to get a stacktrace differently: I attached to the process with java and c/c++ debuggers simultaneously.
Here is the java stacktrace (from java debugger) with insertions of native stacktraces (from c/c++ debugger) (it's right before the process crash):

      === Native stack in c/c++ debugger ===
      __pthread_kill_implementation() at ./nptl/./nptl/pthread_kill.c:44 0x7f2df009eb2c	
      __pthread_kill_internal() at ./nptl/./nptl/pthread_kill.c:78 0x7f2df009eb2c	
      __GI___pthread_kill() at ./nptl/./nptl/pthread_kill.c:89 0x7f2df009eb2c	
      __GI_raise() at ./signal/../sysdeps/posix/raise.c:26 0x7f2df004527e	
      __GI_abort() at ./stdlib/./stdlib/abort.c:79 0x7f2df00288ff	
      os::abort(bool, void const*, void const*) [clone .cold] at 0x7f2deeadc1b9	
      VMError::report_and_die() at 0x7f2defa1a3e6	
      VMError::report_and_die() at 0x7f2defa1abcf	
      VMError::report_and_die() at 0x7f2defa1ac1f	
      JVM_handle_linux_signal() at 0x7f2def86f630	
      <signal handler called>() at 0x7f2df0045330	
      gtk_tree_store_get_path() at /opt/gtk/gtk+3.0-3.24.41/gtk/gtktreestore.c:594 0x7f2d8349392a	
      gtk_tree_store_get_path() at /opt/gtk/gtk+3.0-3.24.41/gtk/gtktreestore.c:610 0x7f2d83493a0c	
      gtk_tree_model_get_path() at /opt/gtk/gtk+3.0-3.24.41/gtk/gtktreemodel.c:1 405 0x7f2d8347c542	
      Java_org_eclipse_swt_internal_gtk_GTK_gtk_1tree_1model_1get_1path() at 0x7f2dc41d4655	
      0x7f2dd7b47112	
      0x7f2dee7fc1c8	
      0x7f2dd7b46d39	
      0x7f2dee7fc1e8	
      0x7f2dd7b46d04	
      0xfffffffffffffff7	
      0x7f2d9c52f298	
      0x7	
      0x7f2d9c536b90	
      0x0	


TreeItem.getParentItem() line: 848	
TreeViewer.getParentItem(Item) line: 229	
TreeViewer(AbstractTreeViewer).getTreePathFromItem(Item) line: 3199	
TreeViewer(AbstractTreeViewer).internalFindItem(TreePath) line: 237	
TreeViewer(AbstractTreeViewer).internalFindItems(Object) line: 214	
TreeViewer.replace(Object, int, Object) line: 438	
TreeCrashBugAuto$TestContentProvider.updateElement(TreePath, int) line: 96	
TreeViewer.virtualLazyUpdateWidget(Widget, int) line: 1003	
TreeViewer.lambda$1(Event) line: 261	
Lambda.handleEvent(Event) line: not available	
EventTable.sendEvent(Event) line: 91	
Display.sendEvent(EventTable, Event) line: 5865	
Tree(Widget).sendEvent(Event) line: 1656	
Tree(Widget).sendEvent(int, Event, boolean) line: 1682	
Tree(Widget).sendEvent(int, Event) line: 1665	
Tree.checkData(TreeItem) line: 375	
Tree.cellDataProc(long, long, long, long, long) line: 307	
Display.cellDataProc(long, long, long, long, long) line: 997	


      === Native stack in c/c++ debugger ===
      apply_cell_attributes() at /opt/gtk/gtk+3.0-3.24.41/gtk/gtkcellarea.c:1 257 0x7f2d8311da3b	
      g_hash_table_foreach() at /opt/gtk/glib2.0-2.80.0/glib/ghash.c:2 117 0x7f2d82d8ef80	
      gtk_cell_area_real_apply_attributes() at /opt/gtk/gtk+3.0-3.24.41/gtk/gtkcellarea.c:1 286 0x7f2d8311db55	
      gtk_cell_area_box_apply_attributes() at /opt/gtk/gtk+3.0-3.24.41/gtk/gtkcellareabox.c:1 310 0x7f2d83127dc5	
      _gtk_marshal_VOID__OBJECT_BOXED_BOOLEAN_BOOLEANv() at /opt/gtk/gtk+3.0-3.24.41/builddir/gtk/gtkmarshalers.c:5 447 0x7f2d830a82e2	
      g_type_class_meta_marshalv() at /opt/gtk/glib2.0-2.80.0/gobject/gclosure.c:1 062 0x7f2d82cd7f7e	
      _g_closure_invoke_va() at /opt/gtk/glib2.0-2.80.0/gobject/gclosure.c:897 0x7f2d82cd7a82	
      signal_emit_valist_unlocked() at /opt/gtk/glib2.0-2.80.0/gobject/gsignal.c:3 424 0x7f2d82cfa81f	
      g_signal_emit_valist() at /opt/gtk/glib2.0-2.80.0/gobject/gsignal.c:3 263 0x7f2d82cfa16e	
      g_signal_emit() at /opt/gtk/glib2.0-2.80.0/gobject/gsignal.c:3 583 0x7f2d82cfbb43	
      gtk_cell_area_apply_attributes() at /opt/gtk/gtk+3.0-3.24.41/gtk/gtkcellarea.c:2 373 0x7f2d83120b52	
      gtk_tree_view_column_cell_set_cell_data() at /opt/gtk/gtk+3.0-3.24.41/gtk/gtktreeviewcolumn.c:2 821 0x7f2d834c9cfc	
      set_cell_data() at /opt/gtk/gtk+3.0-3.24.41/gtk/a11y/gtktreeviewaccessible.c:347 0x7f2d835f85d6	
      create_cell() at /opt/gtk/gtk+3.0-3.24.41/gtk/a11y/gtktreeviewaccessible.c:439 0x7f2d835f890d	
      _gtk_tree_view_accessible_add_state() at /opt/gtk/gtk+3.0-3.24.41/gtk/a11y/gtktreeviewaccessible.c:2 053 0x7f2d835fc039	
      gtk_tree_view_real_set_cursor() at /opt/gtk/gtk+3.0-3.24.41/gtk/gtktreeview.c:13 377 0x7f2d834bc13b	
      gtk_tree_view_row_deleted() at /opt/gtk/gtk+3.0-3.24.41/gtk/gtktreeview.c:9 430 0x7f2d834b1916	
      g_cclosure_marshal_VOID__BOXED() at /opt/gtk/glib2.0-2.80.0/gobject/gmarshal.c:1 628 0x7f2d82cdd612	
      g_closure_invoke() at /opt/gtk/glib2.0-2.80.0/gobject/gclosure.c:834 0x7f2d82cd7763	
      signal_emit_unlocked_R() at /opt/gtk/glib2.0-2.80.0/gobject/gsignal.c:3 888 0x7f2d82cfc894	
      signal_emit_valist_unlocked() at /opt/gtk/glib2.0-2.80.0/gobject/gsignal.c:3 520 0x7f2d82cfb587	
      g_signal_emit_valist() at /opt/gtk/glib2.0-2.80.0/gobject/gsignal.c:3 263 0x7f2d82cfa16e	
      g_signal_emit() at /opt/gtk/glib2.0-2.80.0/gobject/gsignal.c:3 583 0x7f2d82cfbb43	
      gtk_tree_model_row_deleted() at /opt/gtk/gtk+3.0-3.24.41/gtk/gtktreemodel.c:1 914 0x7f2d8347df98	
      gtk_tree_store_remove() at /opt/gtk/gtk+3.0-3.24.41/gtk/gtktreestore.c:1 231 0x7f2d834957a6	
      gtk_tree_store_clear_traverse() at /opt/gtk/gtk+3.0-3.24.41/gtk/gtktreestore.c:1 848 0x7f2d834971d2	
      gtk_tree_store_clear_traverse() at /opt/gtk/gtk+3.0-3.24.41/gtk/gtktreestore.c:1 839 0x7f2d8349718b	
      gtk_tree_store_clear() at /opt/gtk/gtk+3.0-3.24.41/gtk/gtktreestore.c:1 884 0x7f2d83497310	
      Java_org_eclipse_swt_internal_gtk_GTK_gtk_1tree_1store_1clear() at 0x7f2dc41d494d	
      0x7f2dd7b47112	
      0x7f2de801d7b8	
      0x7f2de801d890	
      0xd8	
      0xfffffffffffffff7	
      0x0	


GTK.gtk_tree_store_clear(long) line: not available [native method]	
Tree.removeAll() line: 2960	
TreeViewer.removeAll(Control) line: 290	
TreeViewer(AbstractTreeViewer).lambda$2() line: 1629	
Lambda.run() line: not available	
TreeViewer(StructuredViewer).preservingSelection(Runnable, boolean) line: 1395	
TreeViewer.preservingSelection(Runnable, boolean) line: 368	
TreeViewer(StructuredViewer).preservingSelection(Runnable) line: 1356	
TreeViewer(AbstractTreeViewer).inputChanged(Object, Object) line: 1625	
TreeViewer(ContentViewer).setInput(Object) line: 279	
TreeViewer(StructuredViewer).setInput(Object) line: 1639	
TreeCrashBugAuto.main(String[]) line: 49	

Note that the tree has a scrollbar: on my machine the bug doesn't happen if the window is large enough for the tree to have no scrollbar.

Environment variables to start the snippet
The bug seems to be use-after-free error: SWT uses some pointer that has already been freed in the native gtk code.
Such bugs can be difficult to reproduce: the only happens if the freed memory is overritten with some "bad" values by the time the dangling pointer is accessed again.
In order to increase the probability of the bug showing use this environment variables:

export G_DEBUG=gc-friendly          # glib: fill freed memory with 0s
export G_SLICE=always-malloc      # disable glib's internal memory allocator
export MALLOC_PERTURB_=255  # glibc: fill freed memory with 1s, and fill allocated memory with 0s

This bug is similar to:

Expected behavior
Tree items should be deleted without errors.

Screenshots
See above.

Environment:

  1. Select the platform(s) on which the behavior is seen:
    • All OS
    • Windows
    • Linux
    • macOS
  1. Additional OS info (e.g. OS version, Linux Desktop, etc)
    Ubuntu 24.04.4 LTS
    X.Org 21.1.11
    GTK 3.24.41
    SWT 4.39 (the bug also happens in 4.40RC1) from https://download.eclipse.org/eclipse/downloads/
    JFace 3.39.0 from maven central repo

  2. JRE/JDK version
    OpenJDK 64-Bit Server VM (build 25.0.2+10-Ubuntu-124.04, mixed mode, sharing)

Version since
At least since SWT 4.39.

Workaround (or) Additional context
The workaround described here works for this bug.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions