-
Notifications
You must be signed in to change notification settings - Fork 144
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Gtk3] Bug: SWTException on Table.remove(...) for a row with focus #1606
Comments
om-11-2024
added a commit
to om-11-2024/eclipse.platform.swt
that referenced
this issue
Nov 21, 2024
…ipse-platform#1606 Fix for SWTException on Table.remove(...) with focused row. This bug happens only in Gtk3. Cause: `gtk_list_store_remove(...)` for a focused row invokes `Table.cellDataProc(...)` with not-yet-updated `Table.items`. Fix: remove `TableItem` from `Table.items` before `gtk_list_store_remove(...)`. Fixes eclipse-platform#1606: The exception only happens in Gtk3. Java stacktrace: ```java org.eclipse.swt.SWTException: Widget is disposed at org.eclipse.swt.SWT.error(SWT.java:4922) at org.eclipse.swt.SWT.error(SWT.java:4837) at org.eclipse.swt.SWT.error(SWT.java:4808) at org.eclipse.swt.widgets.Widget.error(Widget.java:597) at org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:512) at org.eclipse.swt.widgets.TableItem.setText(TableItem.java:1363) at org.eclipse.swt.tests.gtk.Test_Gtk3_Table_Remove_Focused_Row.lambda$3(Test_Gtk3_Table_Remove_Focused_Row.java:68) at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:91) at org.eclipse.swt.widgets.Display.sendEvent(Display.java:5857) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1617) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1643) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1626) at org.eclipse.swt.widgets.Table.checkData(Table.java:289) at org.eclipse.swt.widgets.Table.cellDataProc(Table.java:227) at org.eclipse.swt.widgets.Display.cellDataProc(Display.java:995) at org.eclipse.swt.internal.gtk.GTK.gtk_list_store_remove(Native Method) at org.eclipse.swt.widgets.Table.remove(Table.java:2668) ... ``` The main cause of the error is that: 1. when a row with focus is deleted with `gtk_list_store_remove(...)`, then cell data function `Table.cellDataProc(...)` is called for a row after the removed one 2. but inside `Table.cellDataProc(...)` `Table.items` isn't yet updated , therefore `Table.cellDataProc(...)` operates with `TableItem`, which is already disposed but not yet removed from `Table.items` Inside `gtk_list_store_remove(...)` the row is removed from the `GtkTreeModel`, and only then `GtkTreeView` callbacks are invoked. It means that when `Table.cellDataProc(...)` is invoked, the row has already been removed in Gtk3. The fix: remove `TableItem` from `Table.items` before `gtk_list_store_remove(...)` instead of after. Important: I haven't tried to reproduce this bug in GTK4. Os: Ubuntu 24.04.1 LTS Gtk: 3.24.41 Swt: 4.967.8 ================================================= Why `gtk_list_store_remove(...)` invokes `Table.cellDataProc(...)` only for a row with focus and not for ordinary rows? The reason is that in gtk3 when a row with focus is deleted, the next row receives focus, which among other things creates `GtkCellAccessible` (a "cell with focus" for assistive technology in gtk3). Creation of `GtkCellAccessible` invokes cell data function `Table.cellDataProc(...)` - just like it happens when a standard cell in `GtkTreeView` gets rendered. Here is the stacktrace in gtk3 code: ```c apply_cell_attributes() at gtkcellarea.c:1257 g_hash_table_foreach() at ghash.c:2117 gtk_cell_area_real_apply_attributes() at gtkcellarea.c:1286 gtk_cell_area_box_apply_attributes() at gtkcellareabox.c:1310 _gtk_marshal_VOID__OBJECT_BOXED_BOOLEAN_BOOLEANv() at gtkmarshalers.c:5447 g_type_class_meta_marshalv() at gclosure.c:1062 _g_closure_invoke_va() at gclosure.c:897 signal_emit_valist_unlocked() at gsignal.c:3424 g_signal_emit_valist() at gsignal.c:3263 g_signal_emit() at gsignal.c:3583 gtk_cell_area_apply_attributes() at gtkcellarea.c:2373 gtk_tree_view_column_cell_set_cell_data() at gtktreeviewcolumn.c:2821 set_cell_data() at gtktreeviewaccessible.c:347 create_cell() at gtktreeviewaccessible.c:439 _gtk_tree_view_accessible_add_state() at gtktreeviewaccessible.c:2053 gtk_tree_view_real_set_cursor() at gtktreeview.c:13377 gtk_tree_view_row_deleted() at gtktreeview.c:9430 g_cclosure_marshal_VOID__BOXED() at gmarshal.c:1628 g_closure_invoke() at gclosure.c:834 signal_emit_unlocked_R() at gsignal.c:3888 signal_emit_valist_unlocked() at gsignal.c:3520 g_signal_emit_valist() at gsignal.c:3263 g_signal_emit() at gsignal.c:3583 gtk_tree_model_row_deleted() at gtktreemodel.c:1914 gtk_list_store_remove() at gtkliststore.c:1219 Java_org_eclipse_swt_internal_gtk_GTK_gtk_1list_1store_1remove() ``` The code that leads to execution of cell data function for a row with focus is in gtktreeview.c: ``` static void gtk_tree_view_row_deleted (GtkTreeModel *model, GtkTreePath *path, gpointer data) { ... /* If the cursor row got deleted, move the cursor to the next row */ if (tree_view->priv->cursor_node && (tree_view->priv->cursor_node == node || (node->children && (tree_view->priv->cursor_tree == node->children || _gtk_rbtree_contains (node->children, tree_view->priv->cursor_tree))))) { ... cursor_changed = TRUE; } ... if (cursor_changed) { if (cursor_node) { ... gtk_tree_view_real_set_cursor (tree_view, cursor_path, CLEAR_AND_SELECT | CURSOR_INVALID); ... } ... } ... } ```
om-11-2024
added a commit
to om-11-2024/eclipse.platform.swt
that referenced
this issue
Nov 21, 2024
…ipse-platform#1606 Fix for `SWTException` on `Table.remove(...)` with focused row. This bug happens only in Gtk3. Cause: `gtk_list_store_remove(...)` for a focused row invokes `Table.cellDataProc(...)` with not-yet-updated `Table.items`. Fix: remove `TableItem` from `Table.items` before `gtk_list_store_remove(...)`. Fixes eclipse-platform#1606: The exception only happens in Gtk3. Java stacktrace: ```java org.eclipse.swt.SWTException: Widget is disposed at org.eclipse.swt.SWT.error(SWT.java:4922) at org.eclipse.swt.SWT.error(SWT.java:4837) at org.eclipse.swt.SWT.error(SWT.java:4808) at org.eclipse.swt.widgets.Widget.error(Widget.java:597) at org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:512) at org.eclipse.swt.widgets.TableItem.setText(TableItem.java:1363) at org.eclipse.swt.tests.gtk.Test_Gtk3_Table_Remove_Focused_Row.lambda$3(Test_Gtk3_Table_Remove_Focused_Row.java:68) at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:91) at org.eclipse.swt.widgets.Display.sendEvent(Display.java:5857) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1617) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1643) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1626) at org.eclipse.swt.widgets.Table.checkData(Table.java:289) at org.eclipse.swt.widgets.Table.cellDataProc(Table.java:227) at org.eclipse.swt.widgets.Display.cellDataProc(Display.java:995) at org.eclipse.swt.internal.gtk.GTK.gtk_list_store_remove(Native Method) at org.eclipse.swt.widgets.Table.remove(Table.java:2668) ... ``` The main cause of the error is that: 1. when a row with focus is deleted with `gtk_list_store_remove(...)`, then cell data function `Table.cellDataProc(...)` is called for a row after the removed one 2. but inside `Table.cellDataProc(...)` `Table.items` isn't yet updated , therefore `Table.cellDataProc(...)` operates with `TableItem`, which is already disposed but not yet removed from `Table.items` Inside `gtk_list_store_remove(...)` the row is removed from the `GtkTreeModel`, and only then `GtkTreeView` callbacks are invoked. It means that when `Table.cellDataProc(...)` is invoked, the row has already been removed in Gtk3. The fix: remove `TableItem` from `Table.items` before `gtk_list_store_remove(...)` instead of after. Important: I haven't tried to reproduce this bug in GTK4. Os: Ubuntu 24.04.1 LTS Gtk: 3.24.41 Swt: 4.967.8 ================================================= Why `gtk_list_store_remove(...)` invokes `Table.cellDataProc(...)` only for a row with focus and not for ordinary rows? The reason is that in gtk3 when a row with focus is deleted, the next row receives focus, which among other things creates `GtkCellAccessible` (a "cell with focus" for assistive technology in gtk3). Creation of `GtkCellAccessible` invokes cell data function `Table.cellDataProc(...)` - just like it happens when a standard cell in `GtkTreeView` gets rendered. Here is the stacktrace in gtk3 code: ```c apply_cell_attributes() at gtkcellarea.c:1257 g_hash_table_foreach() at ghash.c:2117 gtk_cell_area_real_apply_attributes() at gtkcellarea.c:1286 gtk_cell_area_box_apply_attributes() at gtkcellareabox.c:1310 _gtk_marshal_VOID__OBJECT_BOXED_BOOLEAN_BOOLEANv() at gtkmarshalers.c:5447 g_type_class_meta_marshalv() at gclosure.c:1062 _g_closure_invoke_va() at gclosure.c:897 signal_emit_valist_unlocked() at gsignal.c:3424 g_signal_emit_valist() at gsignal.c:3263 g_signal_emit() at gsignal.c:3583 gtk_cell_area_apply_attributes() at gtkcellarea.c:2373 gtk_tree_view_column_cell_set_cell_data() at gtktreeviewcolumn.c:2821 set_cell_data() at gtktreeviewaccessible.c:347 create_cell() at gtktreeviewaccessible.c:439 _gtk_tree_view_accessible_add_state() at gtktreeviewaccessible.c:2053 gtk_tree_view_real_set_cursor() at gtktreeview.c:13377 gtk_tree_view_row_deleted() at gtktreeview.c:9430 g_cclosure_marshal_VOID__BOXED() at gmarshal.c:1628 g_closure_invoke() at gclosure.c:834 signal_emit_unlocked_R() at gsignal.c:3888 signal_emit_valist_unlocked() at gsignal.c:3520 g_signal_emit_valist() at gsignal.c:3263 g_signal_emit() at gsignal.c:3583 gtk_tree_model_row_deleted() at gtktreemodel.c:1914 gtk_list_store_remove() at gtkliststore.c:1219 Java_org_eclipse_swt_internal_gtk_GTK_gtk_1list_1store_1remove() ``` The code that leads to execution of cell data function for a row with focus is in gtktreeview.c: ``` static void gtk_tree_view_row_deleted (GtkTreeModel *model, GtkTreePath *path, gpointer data) { ... /* If the cursor row got deleted, move the cursor to the next row */ if (tree_view->priv->cursor_node && (tree_view->priv->cursor_node == node || (node->children && (tree_view->priv->cursor_tree == node->children || _gtk_rbtree_contains (node->children, tree_view->priv->cursor_tree))))) { ... cursor_changed = TRUE; } ... if (cursor_changed) { if (cursor_node) { ... gtk_tree_view_real_set_cursor (tree_view, cursor_path, CLEAR_AND_SELECT | CURSOR_INVALID); ... } ... } ... } ```
om-11-2024
added a commit
to om-11-2024/eclipse.platform.swt
that referenced
this issue
Nov 21, 2024
…ipse-platform#1606 Fix for `SWTException` on `Table.remove(...)` with a focused row. Cause: `gtk_list_store_remove(...)` for a focused row invokes `Table.cellDataProc(...)` with not-yet-updated `Table.items`. Fix: remove `TableItem` from `Table.items` before `gtk_list_store_remove(...)`. Fixes eclipse-platform#1606 This bug happens in Gtk3. I haven't tried to reproduce this bug in GTK4. Java stacktrace: ```java org.eclipse.swt.SWTException: Widget is disposed at org.eclipse.swt.SWT.error(SWT.java:4922) at org.eclipse.swt.SWT.error(SWT.java:4837) at org.eclipse.swt.SWT.error(SWT.java:4808) at org.eclipse.swt.widgets.Widget.error(Widget.java:597) at org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:512) at org.eclipse.swt.widgets.TableItem.setText(TableItem.java:1363) at org.eclipse.swt.tests.gtk.Test_Gtk3_Table_Remove_Focused_Row.lambda$3(Test_Gtk3_Table_Remove_Focused_Row.java:68) at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:91) at org.eclipse.swt.widgets.Display.sendEvent(Display.java:5857) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1617) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1643) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1626) at org.eclipse.swt.widgets.Table.checkData(Table.java:289) at org.eclipse.swt.widgets.Table.cellDataProc(Table.java:227) at org.eclipse.swt.widgets.Display.cellDataProc(Display.java:995) at org.eclipse.swt.internal.gtk.GTK.gtk_list_store_remove(Native Method) at org.eclipse.swt.widgets.Table.remove(Table.java:2668) ... ``` The main cause of the error is that: 1. when a row with focus is deleted with `gtk_list_store_remove(...)`, then cell data function `Table.cellDataProc(...)` is called for a row after the removed one 2. but inside `Table.cellDataProc(...)` `Table.items` isn't yet updated , therefore `Table.cellDataProc(...)` operates with `TableItem`, which is already disposed but not yet removed from `Table.items` Inside `gtk_list_store_remove(...)` the row is removed from the `GtkTreeModel`, and only then `GtkTreeView` callbacks are invoked. It means that when `Table.cellDataProc(...)` is invoked, the row has already been removed in Gtk3. The fix: remove `TableItem` from `Table.items` before `gtk_list_store_remove(...)` instead of after. Os: Ubuntu 24.04.1 LTS Gtk: 3.24.41 Swt: 4.967.8 ================================================= Why `gtk_list_store_remove(...)` invokes `Table.cellDataProc(...)` only for a row with focus and not for ordinary rows? The reason is that in gtk3 when a row with focus is deleted, the next row receives focus, which among other things creates `GtkCellAccessible` (a "cell with focus" for assistive technology in gtk3). Creation of `GtkCellAccessible` invokes cell data function `Table.cellDataProc(...)` - just like it happens when a standard cell in `GtkTreeView` gets rendered. Here is the stacktrace in gtk3 code: ```c apply_cell_attributes() at gtkcellarea.c:1257 g_hash_table_foreach() at ghash.c:2117 gtk_cell_area_real_apply_attributes() at gtkcellarea.c:1286 gtk_cell_area_box_apply_attributes() at gtkcellareabox.c:1310 _gtk_marshal_VOID__OBJECT_BOXED_BOOLEAN_BOOLEANv() at gtkmarshalers.c:5447 g_type_class_meta_marshalv() at gclosure.c:1062 _g_closure_invoke_va() at gclosure.c:897 signal_emit_valist_unlocked() at gsignal.c:3424 g_signal_emit_valist() at gsignal.c:3263 g_signal_emit() at gsignal.c:3583 gtk_cell_area_apply_attributes() at gtkcellarea.c:2373 gtk_tree_view_column_cell_set_cell_data() at gtktreeviewcolumn.c:2821 set_cell_data() at gtktreeviewaccessible.c:347 create_cell() at gtktreeviewaccessible.c:439 _gtk_tree_view_accessible_add_state() at gtktreeviewaccessible.c:2053 gtk_tree_view_real_set_cursor() at gtktreeview.c:13377 gtk_tree_view_row_deleted() at gtktreeview.c:9430 g_cclosure_marshal_VOID__BOXED() at gmarshal.c:1628 g_closure_invoke() at gclosure.c:834 signal_emit_unlocked_R() at gsignal.c:3888 signal_emit_valist_unlocked() at gsignal.c:3520 g_signal_emit_valist() at gsignal.c:3263 g_signal_emit() at gsignal.c:3583 gtk_tree_model_row_deleted() at gtktreemodel.c:1914 gtk_list_store_remove() at gtkliststore.c:1219 Java_org_eclipse_swt_internal_gtk_GTK_gtk_1list_1store_1remove() ``` The code that leads to execution of cell data function for a row with focus is in gtktreeview.c: ``` static void gtk_tree_view_row_deleted (GtkTreeModel *model, GtkTreePath *path, gpointer data) { ... /* If the cursor row got deleted, move the cursor to the next row */ if (tree_view->priv->cursor_node && (tree_view->priv->cursor_node == node || (node->children && (tree_view->priv->cursor_tree == node->children || _gtk_rbtree_contains (node->children, tree_view->priv->cursor_tree))))) { ... cursor_changed = TRUE; } ... if (cursor_changed) { if (cursor_node) { ... gtk_tree_view_real_set_cursor (tree_view, cursor_path, CLEAR_AND_SELECT | CURSOR_INVALID); ... } ... } ... } ```
This was referenced Nov 21, 2024
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Describe the bug
SWTException
onTable.remove(...)
for a row with focus.To Reproduce
A standalone SWT snippet to reproduce the behavior:
Just press the "GO" button and the program terminates after printing this to stderr:
Expected behavior
The row should be successfully removed without errors.
Screenshots
Not applicable.
Environment:
Additional OS info (e.g. OS version, Linux Desktop, etc)
Os: Ubuntu 24.04.1 LTS
Xfce: 4.18
Gtk: 3.24.41
Swt: 4.967.8
JRE/JDK version
OpenJDK 64-Bit Server VM (build 17.0.12+7-Ubuntu-1ubuntu224.04, mixed mode, sharing)
Version since
at least since Swt 4.967.8
Workaround (or) Additional context
I will submit a pull request with a fix a little bit later.
The text was updated successfully, but these errors were encountered: