Gtk:ERROR assertion failed -> eclipse closes
Today I encountered a crash of Eclipse (2023-03) under linux where the last entry in the log was:
Gtk:ERROR:../../../../gtk/gtktreestore.c:596:gtk_tree_store_get_path: assertion failed: (G_NODE (iter->user_data)->parent != NULL)
I didn't see any crash or similar, the application just exited suddenly, after a restart I can continue working, but maybe the message helps someone more familiar with GTK to guess what might be the cause, from the message itself it looks like there is a null pointer accessed.
Which GTK version / OS? Wayland or X11?
where the last entry in the log was
Can you attach complete log / error you have?
Reminds me on https://bugs.eclipse.org/bugs/show_bug.cgi?id=182598, which should have been fixed long time ago.
libgtk-3-0:amd64 3.24.5-1 Debian 4.19.194-3 X11
Is there a hs_err_pid*.log file somewhere near eclipse, or in your HOME?
There are some files in the home folder, is there anything particular interesting I should look for?
EDIT: at laest from the file time stamps they seem to not relate here as they are older than the crash...
Look for such file inside Eclipse install folder too. The one from this crash should contain the native backtrace for the crash.
I scanned my whole homefolder recursively and all eclipse install locations but no luck :-\
Also in the past the log contained a short crashlog but not in this case.
The crash log will be in the working directory, if JVM will be able to write one. Crash dump (for gdb) should be enabled in the system, otherwise it will be not created. Ideally you would start Eclipse from the shell / console or redirect all the output to a file, so at least full GTK error log will be available. Also ideally you could remember which action caused the crash and try to reproduce it.
As I see older crashlogs, at least it seems it was sometimes possible to write logs, but I'll try to look for that data if it occurs next time, I wondering if the place is known to cause errors in the past, maybe the c-code can have a null pointer check and maybe print some additional (eclipse/swt related) info that is helpful in debugging?
How can I enable the crash dumps? I currently have encountered the problem again but still no crash files, the RCP application simply exit with
Gtk:ERROR:../../../../gtk/gtktreestore.c:596:gtk_tree_store_get_path: assertion failed: (G_NODE (iter->user_data)->parent != NULL)
@laeubi if you look for hs_err_pid*.log they are generated in start directory. If you look for core files this differs between distributions.
As said I can't find any hs_err_pid*.log files also I do not see the usual crash report, the JVM simply exits as if one has called System.exit(...) :-\
Ideally you would start Eclipse from the shell / console or redirect all the output to a file, so at least full GTK error log will be available. Also ideally you could remember which action caused the crash and try to reproduce it.
If GTK native code crashes JVM process, there will be no JVM crash dump but should be some output on the console. Also check recent kernel errors via dmesg, usually you will see there which process crashed and with which error.
but should be some output on the console
This is the last output from the console (I'm running the application from withing eclipse)
Gtk:ERROR:../../../../gtk/gtktreestore.c:596:gtk_tree_store_get_path: assertion failed: (G_NODE (iter->user_data)->parent != NULL)
check recent kernel errors via dmesg, usually you will see there which process crashed and with which error.
Anything specific to look / grep for? I don't see anything suspicious here, at least nothing with GTK or eclipse or java in the name...
I have now enabled G_MESSAGES_DEBUG=all that are the messages I see right before the application closes:
<application name>: GdkPixbuf-DEBUG: 05:39:12.063: gdk_pixbuf_from_pixdata() called on:
<application name>: GdkPixbuf-DEBUG: 05:39:12.063: Encoding raw
<application name>: GdkPixbuf-DEBUG: 05:39:12.063: Dimensions: 14 x 14
<application name>: GdkPixbuf-DEBUG: 05:39:12.063: Rowstride: 56, Length: 808
<application name>: GdkPixbuf-DEBUG: 05:39:12.063: Copy pixels == false
<application name>: GdkPixbuf-DEBUG: 05:39:12.620: gdk_pixbuf_from_pixdata() called on:
<application name>: GdkPixbuf-DEBUG: 05:39:12.620: Encoding raw
<application name>: GdkPixbuf-DEBUG: 05:39:12.620: Dimensions: 14 x 14
<application name>: GdkPixbuf-DEBUG: 05:39:12.620: Rowstride: 56, Length: 808
<application name>: GdkPixbuf-DEBUG: 05:39:12.620: Copy pixels == false
<application name>: GdkPixbuf-DEBUG: 05:39:14.581: gdk_pixbuf_from_pixdata() called on:
<application name>: GdkPixbuf-DEBUG: 05:39:14.581: Encoding raw
<application name>: GdkPixbuf-DEBUG: 05:39:14.581: Dimensions: 14 x 14
<application name>: GdkPixbuf-DEBUG: 05:39:14.581: Rowstride: 56, Length: 808
<application name>: GdkPixbuf-DEBUG: 05:39:14.581: Copy pixels == false
**
Gtk:ERROR:../../../../gtk/gtktreestore.c:596:gtk_tree_store_get_path: assertion failed: (G_NODE (iter->user_data)->parent != NULL)
this all seem to happen while updating a tree control so maybe some kind of synchronization issue
I have now narrowed it down to the following lets say we have a (virtual) tree, with an item selected, it seems I can trigger this by inserting an item in the tree that is inserted before the selected one where the selected is a child in the hierarchy.
I tried to gather a stacktrace where the user code currently operates before the crash this is the closes user call I can track before application exit:
java.lang.Exception: Stack trace
at java.base/java.lang.Thread.dumpStack(Thread.java:1380)
at <usercode>
at org.eclipse.jface.viewers.TreeViewer.virtualLazyUpdateWidget(TreeViewer.java:998)
at org.eclipse.jface.viewers.TreeViewer.lambda$1(TreeViewer.java:258)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:89)
at org.eclipse.swt.widgets.Display.sendEvent(Display.java:5855)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1529)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1555)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1538)
at org.eclipse.swt.widgets.Tree.checkData(Tree.java:373)
at org.eclipse.swt.widgets.Tree.cellDataProc(Tree.java:305)
at org.eclipse.swt.widgets.Display.cellDataProc(Display.java:994)
at org.eclipse.swt.internal.gtk.GTK.gtk_tree_store_remove(Native Method)
at org.eclipse.swt.widgets.Tree.destroyItem(Tree.java:1292)
at org.eclipse.swt.widgets.TreeItem.destroyWidget(TreeItem.java:351)
at org.eclipse.swt.widgets.Widget.release(Widget.java:1354)
at org.eclipse.swt.widgets.Widget.dispose(Widget.java:543)
at org.eclipse.swt.widgets.TreeItem.dispose(TreeItem.java:1088)
at org.eclipse.jface.viewers.TreeViewer.lambda$4(TreeViewer.java:846)
at org.eclipse.jface.viewers.TreeViewer.preservingSelection(TreeViewer.java:358)
at org.eclipse.jface.viewers.StructuredViewer.preservingSelection(StructuredViewer.java:1359)
at org.eclipse.jface.viewers.TreeViewer.remove(TreeViewer.java:818)
at <usercode>
at org.eclipse.jface.viewers.TreeViewer.virtualLazyUpdateWidget(TreeViewer.java:998)
at org.eclipse.jface.viewers.TreeViewer.lambda$1(TreeViewer.java:258)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:89)
at org.eclipse.swt.widgets.Display.sendEvent(Display.java:5855)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1529)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1555)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1538)
at org.eclipse.swt.widgets.Tree.checkData(Tree.java:373)
at org.eclipse.swt.widgets.Tree.cellDataProc(Tree.java:305)
at org.eclipse.swt.widgets.Display.cellDataProc(Display.java:994)
at org.eclipse.swt.internal.gtk.GTK.gtk_tree_store_remove(Native Method)
at org.eclipse.swt.widgets.Tree.destroyItem(Tree.java:1292)
at org.eclipse.swt.widgets.TreeItem.destroyWidget(TreeItem.java:351)
at org.eclipse.swt.widgets.Widget.release(Widget.java:1354)
at org.eclipse.swt.widgets.Widget.dispose(Widget.java:543)
at org.eclipse.swt.widgets.TreeItem.dispose(TreeItem.java:1088)
at org.eclipse.jface.viewers.TreeViewer.lambda$4(TreeViewer.java:846)
at org.eclipse.jface.viewers.TreeViewer.preservingSelection(TreeViewer.java:358)
at org.eclipse.jface.viewers.StructuredViewer.preservingSelection(StructuredViewer.java:1359)
at org.eclipse.jface.viewers.TreeViewer.remove(TreeViewer.java:818)
at <usercode>
at org.eclipse.jface.viewers.TreeViewer.virtualLazyUpdateWidget(TreeViewer.java:998)
at org.eclipse.jface.viewers.TreeViewer.lambda$1(TreeViewer.java:258)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:89)
at org.eclipse.swt.widgets.Display.sendEvent(Display.java:5855)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1529)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1555)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1538)
at org.eclipse.swt.widgets.Tree.checkData(Tree.java:373)
at org.eclipse.swt.widgets.Tree.cellDataProc(Tree.java:305)
at org.eclipse.swt.widgets.Display.cellDataProc(Display.java:994)
at org.eclipse.swt.internal.gtk.GTK.gtk_tree_store_remove(Native Method)
at org.eclipse.swt.widgets.Tree.destroyItem(Tree.java:1292)
at org.eclipse.swt.widgets.TreeItem.destroyWidget(TreeItem.java:351)
at org.eclipse.swt.widgets.Widget.release(Widget.java:1354)
at org.eclipse.swt.widgets.Widget.dispose(Widget.java:543)
at org.eclipse.swt.widgets.TreeItem.dispose(TreeItem.java:1088)
at org.eclipse.jface.viewers.TreeViewer.lambda$4(TreeViewer.java:846)
at org.eclipse.jface.viewers.TreeViewer.preservingSelection(TreeViewer.java:358)
at org.eclipse.jface.viewers.StructuredViewer.preservingSelection(StructuredViewer.java:1359)
at org.eclipse.jface.viewers.TreeViewer.remove(TreeViewer.java:818)
at <usercode>
at org.eclipse.jface.viewers.TreeViewer.virtualLazyUpdateWidget(TreeViewer.java:998)
at org.eclipse.jface.viewers.TreeViewer.lambda$1(TreeViewer.java:258)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:89)
at org.eclipse.swt.widgets.Display.sendEvent(Display.java:5855)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1529)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1555)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1538)
at org.eclipse.swt.widgets.Tree.checkData(Tree.java:373)
at org.eclipse.swt.widgets.Tree.cellDataProc(Tree.java:305)
at org.eclipse.swt.widgets.Display.cellDataProc(Display.java:994)
at org.eclipse.swt.internal.gtk.GTK.gtk_tree_store_remove(Native Method)
at org.eclipse.swt.widgets.Tree.destroyItem(Tree.java:1292)
at org.eclipse.swt.widgets.TreeItem.destroyWidget(TreeItem.java:351)
at org.eclipse.swt.widgets.Widget.release(Widget.java:1354)
at org.eclipse.swt.widgets.Widget.dispose(Widget.java:543)
at org.eclipse.swt.widgets.TreeItem.dispose(TreeItem.java:1088)
at org.eclipse.jface.viewers.TreeViewer.lambda$4(TreeViewer.java:846)
at org.eclipse.jface.viewers.TreeViewer.preservingSelection(TreeViewer.java:358)
at org.eclipse.jface.viewers.StructuredViewer.preservingSelection(StructuredViewer.java:1359)
at org.eclipse.jface.viewers.TreeViewer.remove(TreeViewer.java:818)
at <usercode>
at org.eclipse.jface.viewers.TreeViewer.virtualLazyUpdateWidget(TreeViewer.java:998)
at org.eclipse.jface.viewers.TreeViewer.lambda$1(TreeViewer.java:258)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:89)
at org.eclipse.swt.widgets.Display.sendEvent(Display.java:5855)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1529)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1555)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1538)
at org.eclipse.swt.widgets.Tree.checkData(Tree.java:373)
at org.eclipse.swt.widgets.Tree.cellDataProc(Tree.java:305)
at org.eclipse.swt.widgets.Display.cellDataProc(Display.java:994)
at org.eclipse.swt.internal.gtk.GTK.gtk_tree_store_remove(Native Method)
at org.eclipse.swt.widgets.Tree.destroyItem(Tree.java:1292)
at org.eclipse.swt.widgets.TreeItem.destroyWidget(TreeItem.java:351)
at org.eclipse.swt.widgets.Widget.release(Widget.java:1354)
at org.eclipse.swt.widgets.Widget.dispose(Widget.java:543)
at org.eclipse.swt.widgets.TreeItem.dispose(TreeItem.java:1088)
at org.eclipse.swt.widgets.Tree.remove(Tree.java:2975)
at org.eclipse.swt.widgets.Tree.setItemCount(Tree.java:3512)
at org.eclipse.swt.widgets.TreeItem.setItemCount(TreeItem.java:1638)
at org.eclipse.jface.viewers.TreeViewer.lambda$5(TreeViewer.java:955)
at org.eclipse.jface.viewers.TreeViewer.preservingSelection(TreeViewer.java:358)
at org.eclipse.jface.viewers.StructuredViewer.preservingSelection(StructuredViewer.java:1359)
at org.eclipse.jface.viewers.TreeViewer.setHasChildren(TreeViewer.java:941)
at <usercode>
at org.eclipse.jface.viewers.TreeViewer.virtualLazyUpdateWidget(TreeViewer.java:998)
at org.eclipse.jface.viewers.TreeViewer.virtualRefreshExpandedItems(TreeViewer.java:706)
at org.eclipse.jface.viewers.TreeViewer.virtualRefreshExpandedItems(TreeViewer.java:714)
at org.eclipse.jface.viewers.TreeViewer.internalRefreshStruct(TreeViewer.java:681)
at org.eclipse.jface.viewers.AbstractTreeViewer.internalRefresh(AbstractTreeViewer.java:1947)
at org.eclipse.jface.viewers.AbstractTreeViewer.internalRefresh(AbstractTreeViewer.java:1904)
at org.eclipse.jface.viewers.AbstractTreeViewer.internalRefresh(AbstractTreeViewer.java:1890)
at org.eclipse.jface.viewers.StructuredViewer.lambda$2(StructuredViewer.java:1459)
at org.eclipse.jface.viewers.StructuredViewer.preservingSelection(StructuredViewer.java:1398)
at org.eclipse.jface.viewers.TreeViewer.preservingSelection(TreeViewer.java:365)
at org.eclipse.jface.viewers.StructuredViewer.preservingSelection(StructuredViewer.java:1359)
at org.eclipse.jface.viewers.StructuredViewer.refresh(StructuredViewer.java:1459)
at org.eclipse.jface.viewers.ColumnViewer.refresh(ColumnViewer.java:526)
at <usercode>
at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:40)
at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:132)
at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:5040)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:4520)
at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1155)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:338)
at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1046)
at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:155)
at org.eclipse.e4.ui.internal.workbench.swt.E4Application.start(E4Application.java:168)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:203)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:136)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:104)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:402)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:255)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:659)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:596)
at org.eclipse.equinox.launcher.Main.run(Main.java:1467)
at org.eclipse.equinox.launcher.Main.main(Main.java:1440)
I was now able to trace this down to the following SWT call(s)
Thread [main] (Suspended (breakpoint at line 547 in TreeItem))
owns: RunnableLock (id=140)
TreeItem.getExpanded() line: 547
TreeViewer.lambda$5(Object, boolean) line: 956
0x00000008012d9fc8.run() line: not available
TreeViewer.preservingSelection(Runnable, boolean) line: 358
TreeViewer(StructuredViewer).preservingSelection(Runnable) line: 1359
TreeViewer.setHasChildren(Object, boolean) line: 941
<UserCode>TreeContentProvider.updateElement(Object, int) line: 85
TreeViewer.virtualLazyUpdateWidget(Widget, int) line: 998
TreeViewer.lambda$1(Event) line: 258
0x00000008012b77a8.handleEvent(Event) line: not available
EventTable.sendEvent(Event) line: 89
Display.sendEvent(EventTable, Event) line: 5855
Tree(Widget).sendEvent(Event) line: 1529
Tree(Widget).sendEvent(int, Event, boolean) line: 1555
Tree(Widget).sendEvent(int, Event) line: 1538
Tree.checkData(TreeItem) line: 373
Tree.cellDataProc(long, long, long, long, long) line: 305
Display.cellDataProc(long, long, long, long, long) line: 994
GTK.gtk_tree_store_remove(long, long) line: not available [native method]
Tree.destroyItem(TreeItem) line: 1292
TreeItem.destroyWidget() line: 351
TreeItem(Widget).release(boolean) line: 1354
TreeItem(Widget).dispose() line: 543
TreeItem.dispose() line: 1088
TreeViewer.lambda$4(Object, int, List) line: 846
0x00000008013e4688.run() line: not available
TreeViewer.preservingSelection(Runnable, boolean) line: 358
TreeViewer(StructuredViewer).preservingSelection(Runnable) line: 1359
TreeViewer.remove(Object, int) line: 818
<UserCode>TreeContentProvider.updateElement(Object, int) line: 89
TreeViewer.virtualLazyUpdateWidget(Widget, int) line: 998
TreeViewer.lambda$1(Event) line: 258
0x00000008012b77a8.handleEvent(Event) line: not available
EventTable.sendEvent(Event) line: 89
Display.sendEvent(EventTable, Event) line: 5855
Tree(Widget).sendEvent(Event) line: 1529
Tree(Widget).sendEvent(int, Event, boolean) line: 1555
Tree(Widget).sendEvent(int, Event) line: 1538
Tree.checkData(TreeItem) line: 373
Tree.cellDataProc(long, long, long, long, long) line: 305
Display.cellDataProc(long, long, long, long, long) line: 994
GTK.gtk_tree_store_remove(long, long) line: not available [native method]
Tree.destroyItem(TreeItem) line: 1292
TreeItem.destroyWidget() line: 351
TreeItem(Widget).release(boolean) line: 1354
TreeItem(Widget).dispose() line: 543
TreeItem.dispose() line: 1088
TreeViewer.lambda$4(Object, int, List) line: 846
0x00000008013e4688.run() line: not available
TreeViewer.preservingSelection(Runnable, boolean) line: 358
TreeViewer(StructuredViewer).preservingSelection(Runnable) line: 1359
TreeViewer.remove(Object, int) line: 818
<UserCode>TreeContentProvider.updateElement(Object, int) line: 89
TreeViewer.virtualLazyUpdateWidget(Widget, int) line: 998
TreeViewer.lambda$1(Event) line: 258
0x00000008012b77a8.handleEvent(Event) line: not available
EventTable.sendEvent(Event) line: 89
Display.sendEvent(EventTable, Event) line: 5855
Tree(Widget).sendEvent(Event) line: 1529
Tree(Widget).sendEvent(int, Event, boolean) line: 1555
Tree(Widget).sendEvent(int, Event) line: 1538
Tree.checkData(TreeItem) line: 373
Tree.cellDataProc(long, long, long, long, long) line: 305
Display.cellDataProc(long, long, long, long, long) line: 994
GTK.gtk_tree_store_remove(long, long) line: not available [native method]
Tree.destroyItem(TreeItem) line: 1292
TreeItem.destroyWidget() line: 351
TreeItem(Widget).release(boolean) line: 1354
TreeItem(Widget).dispose() line: 543
TreeItem.dispose() line: 1088
TreeViewer.lambda$4(Object, int, List) line: 846
0x00000008013e4688.run() line: not available
TreeViewer.preservingSelection(Runnable, boolean) line: 358
TreeViewer(StructuredViewer).preservingSelection(Runnable) line: 1359
TreeViewer.remove(Object, int) line: 818
<UserCode>TreeContentProvider.updateElement(Object, int) line: 89
TreeViewer.virtualLazyUpdateWidget(Widget, int) line: 998
TreeViewer.lambda$1(Event) line: 258
0x00000008012b77a8.handleEvent(Event) line: not available
EventTable.sendEvent(Event) line: 89
Display.sendEvent(EventTable, Event) line: 5855
Tree(Widget).sendEvent(Event) line: 1529
Tree(Widget).sendEvent(int, Event, boolean) line: 1555
Tree(Widget).sendEvent(int, Event) line: 1538
Tree.checkData(TreeItem) line: 373
Tree.cellDataProc(long, long, long, long, long) line: 305
Display.cellDataProc(long, long, long, long, long) line: 994
GTK.gtk_tree_store_remove(long, long) line: not available [native method]
Tree.destroyItem(TreeItem) line: 1292
TreeItem.destroyWidget() line: 351
TreeItem(Widget).release(boolean) line: 1354
TreeItem(Widget).dispose() line: 543
TreeItem.dispose() line: 1088
TreeViewer.lambda$4(Object, int, List) line: 846
0x00000008013e4688.run() line: not available
TreeViewer.preservingSelection(Runnable, boolean) line: 358
TreeViewer(StructuredViewer).preservingSelection(Runnable) line: 1359
TreeViewer.remove(Object, int) line: 818
<UserCode>TreeContentProvider.updateElement(Object, int) line: 89
TreeViewer.virtualLazyUpdateWidget(Widget, int) line: 998
TreeViewer.lambda$1(Event) line: 258
0x00000008012b77a8.handleEvent(Event) line: not available
EventTable.sendEvent(Event) line: 89
Display.sendEvent(EventTable, Event) line: 5855
Tree(Widget).sendEvent(Event) line: 1529
Tree(Widget).sendEvent(int, Event, boolean) line: 1555
Tree(Widget).sendEvent(int, Event) line: 1538
Tree.checkData(TreeItem) line: 373
Tree.cellDataProc(long, long, long, long, long) line: 305
Display.cellDataProc(long, long, long, long, long) line: 994
GTK.gtk_tree_store_remove(long, long) line: not available [native method]
Tree.destroyItem(TreeItem) line: 1292
TreeItem.destroyWidget() line: 351
TreeItem(Widget).release(boolean) line: 1354
TreeItem(Widget).dispose() line: 543
TreeItem.dispose() line: 1088
TreeViewer.lambda$4(Object, int, List) line: 846
0x00000008013e4688.run() line: not available
TreeViewer.preservingSelection(Runnable, boolean) line: 358
TreeViewer(StructuredViewer).preservingSelection(Runnable) line: 1359
TreeViewer.remove(Object, int) line: 818
<UserCode>TreeContentProvider.updateElement(Object, int) line: 89
TreeViewer.virtualLazyUpdateWidget(Widget, int) line: 998
TreeViewer.lambda$1(Event) line: 258
0x00000008012b77a8.handleEvent(Event) line: not available
EventTable.sendEvent(Event) line: 89
Display.sendEvent(EventTable, Event) line: 5855
Tree(Widget).sendEvent(Event) line: 1529
Tree(Widget).sendEvent(int, Event, boolean) line: 1555
Tree(Widget).sendEvent(int, Event) line: 1538
Tree.checkData(TreeItem) line: 373
Tree.cellDataProc(long, long, long, long, long) line: 305
Display.cellDataProc(long, long, long, long, long) line: 994
GTK.gtk_tree_store_remove(long, long) line: not available [native method]
Tree.destroyItem(TreeItem) line: 1292
TreeItem.destroyWidget() line: 351
TreeItem(Widget).release(boolean) line: 1354
TreeItem(Widget).dispose() line: 543
TreeItem.dispose() line: 1088
Tree.remove(long, int, int) line: 2975
Tree.setItemCount(long, int) line: 3512
TreeItem.setItemCount(int) line: 1638
TreeViewer.lambda$5(Object, boolean) line: 955
0x00000008012d9fc8.run() line: not available
TreeViewer.preservingSelection(Runnable, boolean) line: 358
TreeViewer(StructuredViewer).preservingSelection(Runnable) line: 1359
TreeViewer.setHasChildren(Object, boolean) line: 941
<UserCode>TreeContentProvider.updateElement(Object, int) line: 85
TreeViewer.virtualLazyUpdateWidget(Widget, int) line: 998
TreeViewer.virtualRefreshExpandedItems(Widget, Widget, Object, int) line: 706
TreeViewer.virtualRefreshExpandedItems(Widget, Widget, Object, int) line: 714
TreeViewer.internalRefreshStruct(Widget, Object, boolean) line: 681
TreeViewer(AbstractTreeViewer).internalRefresh(Widget, Object, boolean, boolean) line: 1947
TreeViewer(AbstractTreeViewer).internalRefresh(Object, boolean) line: 1904
TreeViewer(AbstractTreeViewer).internalRefresh(Object) line: 1890
TreeViewer(StructuredViewer).lambda$2(Object) line: 1459
0x00000008012b8408.run() line: not available
TreeViewer(StructuredViewer).preservingSelection(Runnable, boolean) line: 1398
TreeViewer.preservingSelection(Runnable, boolean) line: 365
TreeViewer(StructuredViewer).preservingSelection(Runnable) line: 1359
TreeViewer(StructuredViewer).refresh(Object) line: 1459
TreeViewer(ColumnViewer).refresh(Object) line: 526
<UserCode>TreeContentProvider$ChildNode.lambda$4() line: 327
0x00000008013e26a0.run() line: not available
RunnableLock.run(Display) line: 40
Synchronizer.runAsyncMessages(boolean) line: 132
Display.runAsyncMessages(boolean) line: 5040
Display.readAndDispatch() line: 4520
PartRenderingEngine$5.run() line: 1155
Realm.runWithDefault(Realm, Runnable) line: 338
PartRenderingEngine.run(MApplicationElement, IEclipseContext) line: 1046
E4Workbench.createAndRunUI(MApplicationElement) line: 155
E4Application.start(IApplicationContext) line: 168
EclipseAppHandle.run(Object) line: 203
EclipseAppLauncher.runApplication(Object) line: 136
EclipseAppLauncher.start(Object) line: 104
EclipseStarter.run(Object) line: 402
EclipseStarter.run(String[], Runnable) line: 255
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 77
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43
Method.invoke(Object, Object...) line: 568
Main.invokeFramework(String[], URL[]) line: 659
Main.basicRun(String[]) line: 596
Main.run(String[]) line: 1467
Main.main(String[]) line: 1440
I think the problem is with org.eclipse.swt.widgets.TreeItem.destroyWidget() that already has freed some data but not yet marked the item as disposed, then an event happens (maybe even a dispose event ...) and JFace acceses the data from partly disposed widget -> GTK crash!
Actually it seems the SWT.SetData event in org.eclipse.jface.viewers.TreeViewer.hookControl(Control) that causing the crash.
I now have also checked the JFace code it seems at even time the widgets are not marked as disposed so not much JFace can do here :-\
Current hack in my org.eclipse.jface.viewers.ILazyTreeContentProvider.updateElement(Object, int) method;
@Override
public void updateElement(Object parent, int index) {
if(isSwtIssue667()) {
System.err.println("Break out because of https://github.com/eclipse-platform/eclipse.platform.swt/issues/667");
return;
}
....
}
private Boolean isSwtIssue667() {
if(Platform.OS_LINUX.equals(Platform.getOS())) {
return StackWalker.getInstance().walk(stream -> stream.map(StackFrame::getMethodName).anyMatch("gtk_tree_store_remove"::equals));
}
return false;
}
If you happen to make an SWT snippet reproducing the problem, I might find time to fix it,
@laeubi - I am running into the same crash in Eclipse 4.29 when selecting the elements from the TreeViewer with ILazyTreeContentProvider. And your workaround in updateElement() does not work for me. Any other suggestions? Thanks.
Any other suggestions?
as @SyntevoAlex mentioned if you have some snippet or application one can download to see the problem it would be great, I was not able to reproduce it in a smaller snippet.
You can also try to run Eclipse with
export G_SLICE=always-malloc
export MALLOC_PERTURB_=204
Maybe it will help it crash and produce a crash log.
FYI @akurtakov I finally got a reproducer now, it is not purse SWT an requires JFace and looks a bit clumsy but reproduce the problem reliable for me:
package test;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.viewers.ILazyTreeContentProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ITreeSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
public class SnippetVirtualLazyTreeViewerCrash {
private class MyContentProvider implements ILazyTreeContentProvider {
private TreeViewer treeViewer;
@Override
public Object getParent(Object element) {
return ((Node) element).getParent();
}
@Override
public void updateChildCount(Object element, int currentChildCount) {
treeViewer.setChildCount(element, ((Node) element).childs.size());
}
@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
this.treeViewer = (TreeViewer) viewer;
}
@Override
public void updateElement(Object parent, int index) {
System.out.println("Snippet047VirtualLazyTreeViewerCrash.MyContentProvider.updateElement()");
Thread.dumpStack();
Node element = ((Node) parent).childs.get(index);
if (element.childs.isEmpty()) {
System.out.println("Node '" + element.text + " is empty and will no be removed");
treeViewer.remove(parent);
} else {
System.out.println("Node '" + element.text + " will be made permanent");
treeViewer.replace(parent, index, element);
updateChildCount(element, -1);
}
}
}
public class Node {
private final List<Node> childs = new ArrayList<>();
private final Node parent;
private final String text;
public Node(String text, Node parent) {
this.text = text;
this.parent = parent;
}
public Node getParent() {
return parent;
}
@Override
public String toString() {
return text;
}
}
public Snippet047VirtualLazyTreeViewerCrash(Shell shell) {
TreeViewer treeViewer = new TreeViewer(shell, SWT.VIRTUAL | SWT.BORDER);
treeViewer.setLabelProvider(new LabelProvider());
treeViewer.setContentProvider(new MyContentProvider());
treeViewer.setUseHashlookup(true);
Node root = new Node("root", null);
for (int i = 0; i < 10; i++) {
Node child = new Node("Child " + i, root);
root.childs.add(child);
for (int j = 0; j < 5; j++) {
Node subchild = new Node("Child " + ((char) ('A' + j)), child);
child.childs.add(subchild);
}
}
treeViewer.setInput(root);
treeViewer.getTree().setLayoutData(GridDataFactory.fillDefaults().create());
treeViewer.setChildCount(root, root.childs.size());
treeViewer.getTree().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
treeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
ITreeSelection selection = treeViewer.getStructuredSelection();
Object firstElement = selection.getFirstElement();
if (firstElement instanceof Node node) {
Node parent = node.parent;
parent.childs.remove(node);
shell.getDisplay().timerExec(1000, () -> {
treeViewer.refresh(parent);
});
}
}
});
}
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new GridLayout());
new SnippetVirtualLazyTreeViewerCrash(shell);
shell.setSize(800, 600);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
}
It shows you a tree and if you select on an item, it got removed after a 1 second delay. Now try to expand an item --> JVM crash with message
Node 'Child A is empty and will no be removed
Bail out! Gtk:ERROR:../../../gtk/gtktreestore.c:597:gtk_tree_store_get_path: assertion failed: (G_NODE (iter->user_data)->parent != NULL)
**
Gtk:ERROR:../../../gtk/gtktreestore.c:597:gtk_tree_store_get_path: assertion failed: (G_NODE (iter->user_data)->parent != NULL)
https://github.com/user-attachments/assets/c2820a06-6cb5-477f-aaa4-3c6e402c62bb
Observations
-
Initial Tree Population:
- cellDataProc() gets called for rendering cells
- gtk_tree_model_get_path() is called to get paths for items
- checkData() triggers SWT.SetData events for virtual items
-
Item Removal During Expand:
[USER CODE] DirectCrashTest.MyContentProvider.updateElement() - parent=Child 0, index=0 [USER CODE] Node 'SubChild 0.0' is empty and will be removed [JAVA] TreeItem.destroyWidget() - ENTER [JAVA] Tree.destroyItem() - ENTER - handle=139735893161088 [JAVA] Tree.destroyItem() - About to call gtk_tree_store_remove [NATIVE C] gtk_tree_store_remove() - ENTER - store=0x7f16cc5c7bb0, iter=0x7f16cc463480 [JAVA] Tree.cellDataProc() - ENTER - cell=139735893748432, iter=139735895274640 -
Key Finding:
cellDataProc()is being called duringgtk_tree_store_remove()- This happens before gtk_tree_store_remove() completes (before EXIT)
- This is a re-entrant callback situation
-
The Crash Path: When gtk_tree_store_remove() is called, GTK internally triggers callbacks that lead back to cellDataProc(), which then tries to access the TreeItem being removed. This can lead to:
- Accessing partially destroyed GTK tree model nodes
- The assertion
(G_NODE (iter->user_data)->parent != NULL)failing when getExpanded() calls gtk_tree_model_get_path() on a node being removed