Working around a big memory leak in GTK when redrawing a label
Asked Answered
M

2

8

I'm using the latest release of the PyGTK All-in-One installer (2.24.2) for Python 2.7 which includes Cairo 1.10.8, Pango 1.29.4, PyGTK 2.24.0, and PyGobject 2.28.3 (I think).

The following code leaks ~55 MB of memory:

import gtk

window = gtk.Window()
label = gtk.Label()
window.add(label)
window.show_all()
for _ in range(100000):
    label.set_markup('Leaking memory!')
    while gtk.events_pending():
        gtk.main_iteration()

Note: The for loop is in my test script just so I could see the memory consumption increase in Task Manager. It's also essentially what's going on in my real application, except the label text changes at least once per second instead of just being redrawn with the same text each time.

The problem line is label.set_markup(), which leaks about 0.5kB per call so I suspect the problem is in GTK or Cairo somewhere. It's possibly this bug (685959), as pointed out by a commenter.

I tried using objgraph to see if any extra Python objects are showing up in proportion to the number of calls to gtk.Label.set_markup() but there are no excess objects. It follows that calls to gc.collect() don't help, and I tried it to be sure. Python doesn't seem to be aware of the objects which are responsible for the memory consumption.

How do I find this memory leak, and/or work around it? I need to use markup to style some text for this application, but I tried using gtk.Label.set_text() as a workaround and it leaks memory too.

I should note that this application targets Windows so using PyGObject to get GTK 3 is not an option -- GObject introspection is still not available on Windows.

Maes answered 3/5, 2013 at 20:13 Comment(9)
Is that indentation correct? You're running gtk.main_iteration() for as long as there are events after every time you set the label?Rummage
Yes, that is the correct way to do it. This basically turns the main loop inside out.Maes
@Series8217 What is the for loop for?Anaclitic
That was in my test script so I could watch the memory consumption increase in Task Manager. Not necessary to demonstrate the memory leak. Two calls to set_markup() suffices to show that we're leaking memory.Maes
@Series8217 I see. I just tried it on Linux/GTK 2 and in an infinite loop, memory goes from 19.8MB to 20.1MB after a while and stays there. Just my 2 cents, I can't help more than that :)Anaclitic
@Anaclitic Thanks for checking. Perhaps the libraries available on Linux are different and/or more up to date.Maes
There were Windows-specific leaks in GTK that have been fixed only recently. Take a look, for example, at this bug and also this one. You might need to rebuild your GTK.Warp
@Warp It looks like 685959 is probably it. Unfortunately it doesn't seem anyone has released a build compatible with my environment for quite some time.Maes
Here's an experimental build of all-in-one PyGI for Windows. I didn't try it, but heard it's still far from production quality: opensourcepack.blogspot.fr/p/pygobject-pygi-aio.htmlEchinoid
M
3

Bug (685959) is indeed the problem. The bug is fixed in gtk+ 2.24.14. However, 2.24.14 won't compile for win32 (I hope anyone reading my question and answer realizes at this point that GTK is no longer a reasonable choice or cross-platform development).

I applied this patch to 2.24.10 and successfully compiled the result. With my new runtime files it seems to be working.

I used the instructions here to build GTK on Windows with MinGW: http://ingar.intranifty.net/devenv/mingw32/gtk.html

The 32-bit build will fail around gtk-update-icon-cache unless you run the msys shell as administrator. For the 64-bit build, you need to rm gtk/gtk.def before running make. Build and install gtk+ by executing the following commands:

cd $LOCALBUILDDIR && \ wget -c http://ftp.gnome.org/pub/gnome/sources/gtk+/2.24/gtk+-2.24.10.tar.xz && \ xz -d -c gtk+-2.24.10.tar.xz | tar xv && \ cd gtk+-2.24.10 && \ ./configure --prefix=$LOCALDESTDIR --with-gdktarget=win32 \ --with-included-immodules=ime --disable-debug --disable-gtk-doc && \ make && \ make install

I know this isn't a "workaround" like I asked for in my question, but over 6 months without an answer tells me there is no workaround except fixing the bug in the runtime...

Maes answered 14/12, 2013 at 19:29 Comment(0)
C
1

If you need a fixed Gtk+2 runtime for Windows you can use the Gnome Glade Gtk+ 3.8.5 for Windows which includes the fixed Gtk+ 2.24.23 runtime. http://ftp.gnome.org/pub/GNOME/binaries/win32/glade/3.8/glade-3-8-5-installer.exe

Or build latest Gtk+2 from source for Windows which is also easy using the gtk+ tutorial. https://www.gtk.org/download/windows.php

Copy the dlls to your program or add to PATH when build and install your program.

(PyGTK stays the same API version 2.24.0 it is only the link for python to the Gtk+2 runtime.)

Caseinogen answered 6/4, 2018 at 16:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.