Bug 573477 - [GTK3] ToolItem with DROP_DOWN style leaks native memory
Summary: [GTK3] ToolItem with DROP_DOWN style leaks native memory
Status: RESOLVED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 3.8   Edit
Hardware: PC Linux
: P3 normal (vote)
Target Milestone: 4.20 M3   Edit
Assignee: Simeon Andreev CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-05-11 06:42 EDT by Simeon Andreev CLA
Modified: 2021-05-17 07:16 EDT (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Simeon Andreev CLA 2021-05-11 06:42:17 EDT
To reproduce, run the following snippet with VM arguments "-Xmx128M -Xms128M -XX:+AlwaysPreTouch":

	public static void main(String[] args) {
		Display display = new Display();
		Shell shell = new Shell(display);
		shell.setSize(600, 400);
		shell.setLayout(new FillLayout());
		shell.setText("Demo ToolItem leak");
		Composite composite = new Composite(shell, SWT.NONE);
		composite.setLayout(new FillLayout(SWT.VERTICAL));
		ToolBar tb = new ToolBar(composite, SWT.BORDER);

		shell.open();

		AtomicBoolean c = new AtomicBoolean(true);
		Thread t = new Thread(new Runnable() {
			@Override
				public void run() {
					while (c.get()) {
						if (!display.isDisposed()) {
							display.asyncExec(new Runnable() {
								@Override
								public void run() {
									if (!display.isDisposed()) {
										ToolItem ti = new ToolItem(tb, SWT.BORDER | SWT.DROP_DOWN);
										ti.setToolTipText("ToolItem text");
										ti.dispose();
									}
								}
							});
						}
						try {
							Thread.sleep(100);
						} catch (InterruptedException e) {
						}
					}
				}	
		});
		t.start();

		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
		c.set(false);
		try {
			t.join();
		} catch (InterruptedException e) {
		}
		display.dispose();
	}

Observe growing memory consumption. valgrind reports e.g. such leaks:

==29829== 147,168 (72,888 direct, 74,280 indirect) bytes in 3,037 blocks are definitely lost in loss record 11 of 42,451
==29829==    at 0x4C2B017: malloc (vg_replace_malloc.c:380)
==29829==    by 0x2A42068D: g_malloc (in /usr/lib64/libglib-2.0.so.0.5600.1)
==29829==    by 0x2A437C8D: g_slice_alloc (in /usr/lib64/libglib-2.0.so.0.5600.1)
==29829==    by 0x2A416E45: g_list_prepend (in /usr/lib64/libglib-2.0.so.0.5600.1)
==29829==    by 0x26E9A4BE: gtk_container_children_callback (gtkcontainer.c:3307)
==29829==    by 0x26E568F6: gtk_box_forall (gtkbox.c:2671)
==29829==    by 0x26E9FDCA: gtk_container_get_children (gtkcontainer.c:2539)
==29829==    by 0x26AF7877: Java_org_eclipse_swt_internal_gtk3_GTK3_gtk_1container_1get_1children (in /home/sandreev/git/eclipse/eclipse.platform.swt.binaries/bundles/org.eclipse.swt.gtk.linux.x86_64/libswt-pi3-gtk-4944r22.so)

There seem to be 3 callers of GTK3.gtk_container_get_children() in ToolItem, that don't call OS.g_free():

1. ToolItem.createHandle(int)
2. ToolItem.hookEvents()
3. ToolItem.setToolTipText(Shell, String)

Comment from Alexander Miloslavskiy:

> Documentation [1] indicates "transfer
> container", therefore, SWT must free the list itself, but not the
> elements inside. Also, it easy to see that even SWT does it properly in
> other places.
>
> [1]
> https://developer.gnome.org/gtk3/stable/GtkContainer.html#gtk-container-get-children
Comment 1 Eclipse Genie CLA 2021-05-12 08:48:14 EDT
New Gerrit change created: https://git.eclipse.org/r/c/platform/eclipse.platform.swt/+/180522
Comment 3 Simeon Andreev CLA 2021-05-17 05:40:45 EDT
I trace one of the calls to gtk_container_get_children() without a matching free (the one in ToolItem.createHandle()) back to bug 46025, see commit:
 https://git.eclipse.org/c/platform/eclipse.platform.swt.git/commit/?id=1c6100db3e7e2869dd9939a388c01ffe02266ae6

And in particular:

https://git.eclipse.org/c/platform/eclipse.platform.swt.git/diff/bundles/org.eclipse.swt/Eclipse%20SWT/gtk/org/eclipse/swt/widgets/ToolItem.java?id=1c6100db3e7e2869dd9939a388c01ffe02266ae6

The code did get moved around a couple of times, but I think this is the first commit that adds it.

Its of course possible that GTK changed to require a free, but that seems unlikely (I don't know much about GTK API evolution though, I might be wrong).