Community
Participate
Working Groups
To reproduce, run the following snippet: public static void main(String[] args) { Display display = new Display(); final Image image = display.getSystemImage(SWT.ICON_INFORMATION); Shell shell = new Shell(display); shell.setText("Test Tree leak based on SWT example: Images on the right side of the TreeItem"); shell.setLayout(new FillLayout()); shell.setSize(500, 200); shell.open(); AtomicBoolean c = new AtomicBoolean(true); Thread t = new Thread(new Runnable() { AtomicInteger i = new AtomicInteger(0); Tree tree; List<TreeItem> items; @Override public void run() { while (c.get() && !display.isDisposed()) { display.asyncExec(new Runnable() { @Override public void run() { tree = new Tree(shell, SWT.MULTI | SWT.FULL_SELECTION); tree.setHeaderVisible(true); tree.setLinesVisible(true); int columnCount = 4; for (int i = 0; i < columnCount; i++) { TreeColumn column = new TreeColumn(tree, SWT.NONE); column.setText("Column " + i); } items = new ArrayList<>(); int itemCount = 3; for (int i = 0; i < itemCount; i++) { TreeItem item1 = new TreeItem(tree, SWT.NONE); item1.setText("item " + i); for (int c = 1; c < columnCount; c++) { item1.setText(c, "item [" + i + "-" + c + "]"); item1.setImage(c, image); } items.add(item1); } for (int i = 0; i < columnCount; i++) { tree.getColumn(i).pack(); } } }); try { Thread.sleep(1000); } catch (InterruptedException e) { } display.asyncExec(new Runnable() { @Override public void run() { int index = i.getAndIncrement() % items.size(); tree.setSelection(items.get(index)); } }); try { Thread.sleep(1000); } catch (InterruptedException e) { } display.asyncExec(new Runnable() { @Override public void run() { tree.dispose(); tree = null; items = null; } }); try { Thread.sleep(1000); } catch (InterruptedException e) { } } } }); t.start(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } c.set(false); if (image != null) image.dispose(); display.dispose(); } jemalloc reports the memory leak as: [2688 bytes leaked] je_prof_backtrace (/home/sandreev/git/misc/jemalloc/src/prof.c:636 (discriminator 2)) je_malloc_default (/home/sandreev/git/misc/jemalloc/src/jemalloc.c:2289) g_malloc (??:?) g_slice_alloc (??:?) g_slice_alloc0 (??:?) g_type_create_instance (??:?) g_object_unref (??:?) g_object_new_valist (??:?) g_object_new (??:?) gtk_renderer_cell_accessible_new (/usr/src/debug/gtk+-3.22.30/gtk/a11y/gtkrenderercellaccessible.c:116) create_cell (/usr/src/debug/gtk+-3.22.30/gtk/a11y/gtktreeviewaccessible.c:424) _gtk_tree_view_accessible_add_state (/usr/src/debug/gtk+-3.22.30/gtk/a11y/gtktreeviewaccessible.c:1984) gtk_tree_view_real_set_cursor (/usr/src/debug/gtk+-3.22.30/gtk/gtktreeview.c:13313) gtk_tree_view_set_cursor_on_cell (/usr/src/debug/gtk+-3.22.30/gtk/gtktreeview.c:13440) Java_org_eclipse_swt_internal_gtk_GTK_gtk_1tree_1view_1set_1cursor (??:?) ?? (??:0) If the snippet runs for a longer time: [27264 bytes leaked] je_prof_backtrace (/home/sandreev/git/misc/jemalloc/src/prof.c:636 (discriminator 2)) je_malloc_default (/home/sandreev/git/misc/jemalloc/src/jemalloc.c:2289) g_malloc (??:?) g_slice_alloc (??:?) g_slice_alloc0 (??:?) g_type_create_instance (??:?) g_object_unref (??:?) g_object_new_valist (??:?) g_object_new (??:?) gtk_renderer_cell_accessible_new (/usr/src/debug/gtk+-3.22.30/gtk/a11y/gtkrenderercellaccessible.c:116) create_cell (/usr/src/debug/gtk+-3.22.30/gtk/a11y/gtktreeviewaccessible.c:424) _gtk_tree_view_accessible_add_state (/usr/src/debug/gtk+-3.22.30/gtk/a11y/gtktreeviewaccessible.c:1984) gtk_tree_view_real_set_cursor (/usr/src/debug/gtk+-3.22.30/gtk/gtktreeview.c:13313) gtk_tree_view_set_cursor_on_cell (/usr/src/debug/gtk+-3.22.30/gtk/gtktreeview.c:13440) Java_org_eclipse_swt_internal_gtk_GTK_gtk_1tree_1view_1set_1cursor (??:?) ?? (??:0)
I cannot reproduce the leak without creating and disposing trees, so I guess the leak is per-tree and not per select call.
Reproducible also with a more trivial snippet: public static void main(String[] args) { int n = 1; Display display = new Display(); final Image image = display.getSystemImage(SWT.ICON_INFORMATION); Shell shell = new Shell(display); shell.setText("Test Tree leak based on SWT example: Images on the right side of the TreeItem"); shell.setLayout(new FillLayout(SWT.VERTICAL)); for (int j = 0; j < n; ++j) { Tree tree = new Tree(shell, SWT.MULTI | SWT.FULL_SELECTION); tree.setHeaderVisible(true); tree.setLinesVisible(true); int columnCount = 4; for (int i = 0; i < columnCount; i++) { TreeColumn column = new TreeColumn(tree, SWT.NONE); column.setText("Column " + i); } List<TreeItem> items = new ArrayList<>(); int itemCount = 3; for (int i = 0; i < itemCount; i++) { TreeItem item1 = new TreeItem(tree, SWT.NONE); item1.setText("item " + i); for (int c = 1; c < columnCount; c++) { item1.setText(c, "item [" + i + "-" + c + "]"); item1.setImage(c, image); } items.add(item1); } for (int i = 0; i < columnCount; i++) { tree.getColumn(i).pack(); } tree.setSelection(items.get(j % items.size())); } shell.setSize(500, 1000); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } if (image != null) image.dispose(); display.dispose(); } For n = 1: [384 bytes leaked] je_prof_backtrace (/home/sandreev/git/misc/jemalloc/src/prof.c:636 (discriminator 2)) je_malloc_default (/home/sandreev/git/misc/jemalloc/src/jemalloc.c:2289) g_malloc (??:?) g_slice_alloc (??:?) g_slice_alloc0 (??:?) g_type_create_instance (??:?) g_object_unref (??:?) g_object_new_valist (??:?) g_object_new (??:?) gtk_renderer_cell_accessible_new (/usr/src/debug/gtk+-3.22.30/gtk/a11y/gtkrenderercellaccessible.c:116) create_cell (/usr/src/debug/gtk+-3.22.30/gtk/a11y/gtktreeviewaccessible.c:424) _gtk_tree_view_accessible_add_state (/usr/src/debug/gtk+-3.22.30/gtk/a11y/gtktreeviewaccessible.c:1984) gtk_tree_view_real_set_cursor (/usr/src/debug/gtk+-3.22.30/gtk/gtktreeview.c:13313) gtk_tree_view_set_cursor_on_cell (/usr/src/debug/gtk+-3.22.30/gtk/gtktreeview.c:13440) Java_org_eclipse_swt_internal_gtk_GTK_gtk_1tree_1view_1set_1cursor (??:?) ?? (??:0) For n = 5: [1920 bytes leaked] je_prof_backtrace (/home/sandreev/git/misc/jemalloc/src/prof.c:636 (discriminator 2)) je_malloc_default (/home/sandreev/git/misc/jemalloc/src/jemalloc.c:2289) g_malloc (??:?) g_slice_alloc (??:?) g_slice_alloc0 (??:?) g_type_create_instance (??:?) g_object_unref (??:?) g_object_new_valist (??:?) g_object_new (??:?) gtk_renderer_cell_accessible_new (/usr/src/debug/gtk+-3.22.30/gtk/a11y/gtkrenderercellaccessible.c:116) create_cell (/usr/src/debug/gtk+-3.22.30/gtk/a11y/gtktreeviewaccessible.c:424) _gtk_tree_view_accessible_add_state (/usr/src/debug/gtk+-3.22.30/gtk/a11y/gtktreeviewaccessible.c:1984) gtk_tree_view_real_set_cursor (/usr/src/debug/gtk+-3.22.30/gtk/gtktreeview.c:13313) gtk_tree_view_set_cursor_on_cell (/usr/src/debug/gtk+-3.22.30/gtk/gtktreeview.c:13440) Java_org_eclipse_swt_internal_gtk_GTK_gtk_1tree_1view_1set_1cursor (??:?) ?? (??:0) Something used by GTK+ is not being freed correctly. When I try similar code with a GTK+ snippet, I don't see a leak (but maybe I'm missing something that SWT does): #include <gtk/gtk.h> enum { COL_URI = 0, NUM_COLS } ; // gcc -g table.c `pkg-config --cflags --libs gtk+-3.0` -o table int main (int argc, char **argv) { GtkWidget *window, *scrolled_window, *box, *tree; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); g_signal_connect(window, "delete_event", gtk_main_quit, NULL); gtk_window_set_default_size(GTK_WINDOW(window), 200, 200); scrolled_window = gtk_scrolled_window_new (NULL, NULL); gtk_container_add (GTK_CONTAINER (window), scrolled_window); box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); gtk_container_add(GTK_CONTAINER(scrolled_window), box); int n = 1; int i; for (i = 0; i < n; ++i) { GtkTreeViewColumn *col1; GtkCellRenderer *renderer; GtkListStore *liststore; liststore = gtk_list_store_new(NUM_COLS, G_TYPE_STRING); tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(liststore)); g_object_unref(liststore); /* destroy model with view */ col1 = gtk_tree_view_column_new();; renderer = gtk_cell_renderer_text_new(); gtk_tree_view_column_set_title(col1, "column"); gtk_tree_view_append_column(GTK_TREE_VIEW(tree), col1); gtk_tree_view_column_pack_start(col1, renderer, TRUE); gtk_tree_view_column_add_attribute(col1, renderer, "text", COL_URI); gtk_tree_view_column_set_fixed_width(col1, 150); gtk_tree_view_column_set_resizable(col1, TRUE); GtkTreeStore *treestore; treestore = gtk_tree_store_new(NUM_COLS, G_TYPE_STRING); gtk_tree_view_set_model(GTK_TREE_VIEW(tree), NULL); gtk_tree_view_set_model(GTK_TREE_VIEW(tree), GTK_TREE_MODEL(treestore)); GtkTreeIter iter; int j; for (j = 0; j < 3; ++j) { gtk_tree_store_append(treestore, &iter, NULL); gtk_tree_store_set(treestore, &iter, COL_URI, "item", -1); } GtkTreePath *path; path = gtk_tree_model_get_path (GTK_TREE_MODEL(treestore), &iter); gtk_tree_view_set_cursor (GTK_TREE_VIEW(tree), path, col1, FALSE); gtk_tree_path_free (path); gtk_box_pack_start(GTK_BOX(box), tree, TRUE, TRUE, 0); } gtk_widget_show_all(window); gtk_main(); return 0; } If I simplify the SWT snippet more, to be like the GTK+ snippet above, I still see the same leak (though somewhat less memory is leaked): public static void main(String[] args) { int n = 1; Display display = new Display(); Shell shell = new Shell(display); shell.setText("tree"); shell.setLayout(new FillLayout(SWT.VERTICAL)); for (int j = 0; j < n; ++j) { Tree tree = new Tree(shell, SWT.MULTI | SWT.FULL_SELECTION); tree.setHeaderVisible(true); tree.setLinesVisible(true); TreeColumn column = new TreeColumn(tree, SWT.NONE); column.setText("column"); List<TreeItem> items = new ArrayList<>(); int itemCount = 3; for (int i = 0; i < itemCount; i++) { TreeItem item1 = new TreeItem(tree, SWT.NONE); item1.setText(new String[] { "text" }); items.add(item1); } column.pack(); tree.setSelection(items.get(/* j % items.size() */2)); } shell.setSize(500, 1000); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } display.dispose(); } n = 1: [160 bytes leaked] je_prof_backtrace (/home/sandreev/git/misc/jemalloc/src/prof.c:636 (discriminator 2)) je_malloc_default (/home/sandreev/git/misc/jemalloc/src/jemalloc.c:2289) g_malloc (??:?) g_slice_alloc (??:?) g_slice_alloc0 (??:?) g_type_create_instance (??:?) g_object_unref (??:?) g_object_new_with_properties (??:?) g_object_new (??:?) gtk_container_cell_accessible_new (/usr/src/debug/gtk+-3.22.30/gtk/a11y/gtkcontainercellaccessible.c:131) create_cell (/usr/src/debug/gtk+-3.22.30/gtk/a11y/gtktreeviewaccessible.c:424) _gtk_tree_view_accessible_add_state (/usr/src/debug/gtk+-3.22.30/gtk/a11y/gtktreeviewaccessible.c:1984) gtk_tree_view_real_set_cursor (/usr/src/debug/gtk+-3.22.30/gtk/gtktreeview.c:13313) gtk_tree_view_set_cursor_on_cell (/usr/src/debug/gtk+-3.22.30/gtk/gtktreeview.c:13440) Java_org_eclipse_swt_internal_gtk_GTK_gtk_1tree_1view_1set_1cursor (??:?) ?? (??:0) n = 5: [800 bytes leaked] je_prof_backtrace (/home/sandreev/git/misc/jemalloc/src/prof.c:636 (discriminator 2)) je_malloc_default (/home/sandreev/git/misc/jemalloc/src/jemalloc.c:2289) g_malloc (??:?) g_slice_alloc (??:?) g_slice_alloc0 (??:?) g_type_create_instance (??:?) g_object_unref (??:?) g_object_new_with_properties (??:?) g_object_new (??:?) gtk_container_cell_accessible_new (/usr/src/debug/gtk+-3.22.30/gtk/a11y/gtkcontainercellaccessible.c:131) create_cell (/usr/src/debug/gtk+-3.22.30/gtk/a11y/gtktreeviewaccessible.c:424) _gtk_tree_view_accessible_add_state (/usr/src/debug/gtk+-3.22.30/gtk/a11y/gtktreeviewaccessible.c:1984) gtk_tree_view_real_set_cursor (/usr/src/debug/gtk+-3.22.30/gtk/gtktreeview.c:13313) gtk_tree_view_set_cursor_on_cell (/usr/src/debug/gtk+-3.22.30/gtk/gtktreeview.c:13440) Java_org_eclipse_swt_internal_gtk_GTK_gtk_1tree_1view_1set_1cursor (??:?) ?? (??:0)
Looks like the leaking code runs only if there is more than 1 renderer for a column. So I've updated my GTK+ snippet: #include <gtk/gtk.h> enum { COL_URI = 0, NUM_COLS } ; // gcc -g table.c `pkg-config --cflags --libs gtk+-3.0` -o table int main (int argc, char **argv) { GtkWidget *window, *scrolled_window, *box, *tree; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); g_signal_connect(window, "delete_event", gtk_main_quit, NULL); gtk_window_set_default_size(GTK_WINDOW(window), 500, 1000); scrolled_window = gtk_scrolled_window_new (NULL, NULL); gtk_container_add (GTK_CONTAINER (window), scrolled_window); box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); gtk_container_add(GTK_CONTAINER(scrolled_window), box); int n = 1; int i; for (i = 0; i < n; ++i) { GtkTreeViewColumn *col1; GtkCellRenderer *renderer; GtkListStore *liststore; liststore = gtk_list_store_new(NUM_COLS, G_TYPE_STRING); tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(liststore)); g_object_unref(liststore); /* destroy model with view */ col1 = gtk_tree_view_column_new(); gtk_tree_view_column_set_title(col1, "column"); gtk_tree_view_append_column(GTK_TREE_VIEW(tree), col1); renderer = gtk_cell_renderer_text_new(); gtk_tree_view_column_pack_start(col1, renderer, TRUE); gtk_tree_view_column_add_attribute(col1, renderer, "text", COL_URI + 0); renderer = gtk_cell_renderer_pixbuf_new(); gtk_tree_view_column_pack_start(col1, renderer, TRUE); //gtk_tree_view_column_add_attribute(col1, renderer, "pixbuf", COL_URI + 0); gtk_tree_view_column_set_fixed_width(col1, 150); gtk_tree_view_column_set_resizable(col1, TRUE); gtk_box_pack_start(GTK_BOX(box), tree, TRUE, TRUE, 0); GtkTreeStore *treestore; treestore = gtk_tree_store_new(NUM_COLS, G_TYPE_STRING); gtk_tree_view_set_model(GTK_TREE_VIEW(tree), NULL); gtk_tree_view_set_model(GTK_TREE_VIEW(tree), GTK_TREE_MODEL(treestore)); GtkTreeIter iter; int j; for (j = 0; j < 3; ++j) { gtk_tree_store_append(treestore, &iter, NULL); gtk_tree_store_set(treestore, &iter, COL_URI, "item", -1); } GtkTreePath *path; path = gtk_tree_model_get_path (GTK_TREE_MODEL(treestore), &iter); gtk_tree_view_set_cursor (GTK_TREE_VIEW(tree), path, col1, FALSE); gtk_tree_path_free (path); } gtk_widget_show_all(window); gtk_main(); return 0; } jemalloc now shows the same leak: n = 1: [160 bytes leaked] je_prof_backtrace (/home/sandreev/git/misc/jemalloc/src/prof.c:636 (discriminator 2)) je_malloc_default (/home/sandreev/git/misc/jemalloc/src/jemalloc.c:2289) g_malloc (??:?) g_slice_alloc (??:?) g_slice_alloc0 (??:?) g_type_create_instance (??:?) g_object_unref (??:?) g_object_new_with_properties (??:?) g_object_new (??:?) gtk_container_cell_accessible_new (/usr/src/debug/gtk+-3.22.30/gtk/a11y/gtkcontainercellaccessible.c:131) create_cell (/usr/src/debug/gtk+-3.22.30/gtk/a11y/gtktreeviewaccessible.c:424) _gtk_tree_view_accessible_add_state (/usr/src/debug/gtk+-3.22.30/gtk/a11y/gtktreeviewaccessible.c:1984) gtk_tree_view_real_set_cursor (/usr/src/debug/gtk+-3.22.30/gtk/gtktreeview.c:13313) gtk_tree_view_set_cursor_on_cell (/usr/src/debug/gtk+-3.22.30/gtk/gtktreeview.c:13440) ?? (??:0) __libc_start_main (/usr/src/debug/glibc-2.17-c758a686/csu/../csu/libc-start.c:274) ?? (??:0) n = 5: [800 bytes leaked] je_prof_backtrace (/home/sandreev/git/misc/jemalloc/src/prof.c:636 (discriminator 2)) je_malloc_default (/home/sandreev/git/misc/jemalloc/src/jemalloc.c:2289) g_malloc (??:?) g_slice_alloc (??:?) g_slice_alloc0 (??:?) g_type_create_instance (??:?) g_object_unref (??:?) g_object_new_with_properties (??:?) g_object_new (??:?) gtk_container_cell_accessible_new (/usr/src/debug/gtk+-3.22.30/gtk/a11y/gtkcontainercellaccessible.c:131) create_cell (/usr/src/debug/gtk+-3.22.30/gtk/a11y/gtktreeviewaccessible.c:424) _gtk_tree_view_accessible_add_state (/usr/src/debug/gtk+-3.22.30/gtk/a11y/gtktreeviewaccessible.c:1984) gtk_tree_view_real_set_cursor (/usr/src/debug/gtk+-3.22.30/gtk/gtktreeview.c:13313) gtk_tree_view_set_cursor_on_cell (/usr/src/debug/gtk+-3.22.30/gtk/gtktreeview.c:13440) ?? (??:0) __libc_start_main (/usr/src/debug/glibc-2.17-c758a686/csu/../csu/libc-start.c:274) ?? (??:0) n = 12: [1920 bytes leaked] je_prof_backtrace (/home/sandreev/git/misc/jemalloc/src/prof.c:636 (discriminator 2)) je_malloc_default (/home/sandreev/git/misc/jemalloc/src/jemalloc.c:2289) g_malloc (??:?) g_slice_alloc (??:?) g_slice_alloc0 (??:?) g_type_create_instance (??:?) g_object_unref (??:?) g_object_new_with_properties (??:?) g_object_new (??:?) gtk_container_cell_accessible_new (/usr/src/debug/gtk+-3.22.30/gtk/a11y/gtkcontainercellaccessible.c:131) create_cell (/usr/src/debug/gtk+-3.22.30/gtk/a11y/gtktreeviewaccessible.c:424) _gtk_tree_view_accessible_add_state (/usr/src/debug/gtk+-3.22.30/gtk/a11y/gtktreeviewaccessible.c:1984) gtk_tree_view_real_set_cursor (/usr/src/debug/gtk+-3.22.30/gtk/gtktreeview.c:13313) gtk_tree_view_set_cursor_on_cell (/usr/src/debug/gtk+-3.22.30/gtk/gtktreeview.c:13440) ?? (??:0) __libc_start_main (/usr/src/debug/glibc-2.17-c758a686/csu/../csu/libc-start.c:274) ?? (??:0) n = 21: [3360 bytes leaked] je_prof_backtrace (/home/sandreev/git/misc/jemalloc/src/prof.c:636 (discriminator 2)) je_malloc_default (/home/sandreev/git/misc/jemalloc/src/jemalloc.c:2289) g_malloc (??:?) g_slice_alloc (??:?) g_slice_alloc0 (??:?) g_type_create_instance (??:?) g_object_unref (??:?) g_object_new_with_properties (??:?) g_object_new (??:?) gtk_container_cell_accessible_new (/usr/src/debug/gtk+-3.22.30/gtk/a11y/gtkcontainercellaccessible.c:131) create_cell (/usr/src/debug/gtk+-3.22.30/gtk/a11y/gtktreeviewaccessible.c:424) _gtk_tree_view_accessible_add_state (/usr/src/debug/gtk+-3.22.30/gtk/a11y/gtktreeviewaccessible.c:1984) gtk_tree_view_real_set_cursor (/usr/src/debug/gtk+-3.22.30/gtk/gtktreeview.c:13313) gtk_tree_view_set_cursor_on_cell (/usr/src/debug/gtk+-3.22.30/gtk/gtktreeview.c:13440) ?? (??:0) __libc_start_main (/usr/src/debug/glibc-2.17-c758a686/csu/../csu/libc-start.c:274) ?? (??:0) Alexander, do you have time to double check this? It would be quite unfortunate if the leak is in GTK+, since getting a fix might takes months, years, or we might not get a fix at all...
Seems to be a GTK bug indeed: https://gitlab.gnome.org/GNOME/gtk/-/issues/3981
GTK received a fix for this bug.
(In reply to Alexandr Miloslavskiy from comment #5) > GTK received a fix for this bug. Alexander, did you test the fix? I tried cherry-picking and compiling (as well as adding prints to ensure I use the compiled code). I still see the same memory leak (both with the GTK+ snippet and with SWT) reported by jemalloc.
No, I didn't test it. Do you also see the leak with the GTK snippet I posted in the bug?
(In reply to Alexandr Miloslavskiy from comment #7) > No, I didn't test it. Do you also see the leak with the GTK snippet I posted > in the bug? I'll try next week, checked only with the snippets from this ticket (the GTK+ one is listed on the RHEL bugzilla ticket).
Is it possible that you're confusing two bugs? You only mentioned RHEL ticket on the other one. Sure, I'll wait for your results. I also have a lot to do :)
(In reply to Alexandr Miloslavskiy from comment #9) > Is it possible that you're confusing two bugs? You only mentioned RHEL > ticket on the other one. > > Sure, I'll wait for your results. I also have a lot to do :) Yes, I still see the leaks reported by jemalloc with the proposed fix, when I use the snippet from: https://gitlab.gnome.org/GNOME/gtk/-/issues/3981 I have opened tickets at RHEL for the problem: RHEL bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1965195 RHEL support case: https://access.redhat.com/support/cases/#/case/02950850 Sorry for not mentioning this earlier.
I have tested it myself and the fix seems to work. Simeon, I think that you only cherry-picked one commit, but two commits are necessary to fix the leak. I suggest that you build GTK from 'gtk-3-24' branch, where the fix is already merged via 90e8d7ff.
I've cherry-picked 2 commits: commit 27b3a31dcf66ef7e810945d9aba9dfd8cca017dc (HEAD -> gtk-3-22-jep2587) Author: Matthias Clasen <mclasen@redhat.com> Date: Fri Jun 11 08:53:46 2021 -0400 a11y: Fix ref counting in tree views GtkContainerCellAccessible wasn't unsetting accessible parents. Fix that. By itself, this doesn't help for freeing a memory leak, since AtkObject keeps a ref on its parent, so we never free the GtkContainerCellAccessible as long as it has children. commit d023ec31aa3e2b01f12ad1b30c27694619884053 Author: Matthias Clasen <mclasen@redhat.com> Date: Fri Jun 11 08:55:48 2021 -0400 a11y: Plug a memory leak with treeviews We need to explicitly remove the children from a GtkContainerCellAccessible, since they otherwise keep the parent alive. Fixes: #3981 RHEL 7 is on GTK 3.22.30. I doubt we will update our R&D workstations to GTK 3.24.x, as long as our RHEL version doesn't use that GTK version.
I imagine that even if we managed to backport the GTK patches, this still won't help you, because you won't be installing patched GTK to all workstations?
(In reply to Alexandr Miloslavskiy from comment #13) > I imagine that even if we managed to backport the GTK patches, this still > won't help you, because you won't be installing patched GTK to all > workstations? We (me & Andrey) expect RHEL support to backport (working) fixes to GTK 3.22.x. After that GTK version is available from RHEL, we'll update to it.
I see. The patch seems to solve the problem in 3.24. Backporting it to 3.22 is something my boss won't approve, so unfortunately I can't help with that.
OK, I was prompted on the RHEL bugzilla ticket to double check. Likely I missed a "make clean" when checking the fix, as I don't see the leaks any more. So the fix should be working also for GTK 3.22.x.
Perfect! Then I think this issue can be considered as RESOLVED NOT_ECLIPSE? I don't think that SWT can reasonably work around this GTK problem, because the memory to be freed is buried in internals.
The memory leak is in GTK3, see: https://gitlab.gnome.org/GNOME/gtk/-/issues/3981
Thanks for the help Alexander!