rougier / freetype-py

Python binding for the freetype library
Other
298 stars 88 forks source link

possible memory leaks and issues during finalizer #173

Open carandraug opened 1 year ago

carandraug commented 1 year ago

There has been some hints that the current implementation may have memory leaks and that FT_Done_* is not always called as expected. Related issues include #44 and #169, and the discussion in the pull request #171.

  1. The core of issue #169 and another described in the comments of #44 is what happens during interpreter shutdown, namely that we can't rely on the FT_Done_* functions to exist at that step. This was fixed for Face in pull request #171. However, I think we're making the same mistake in Glyph.__del__ and Stroker.__del__. I can prepare a PR for this.

  2. The issue #44 and some of the comments in issue #169 and PR #171 seem to hint to some memory leaks but it's not clear to me how to reproduce it.

HinTak commented 1 year ago

Calling it a memory leak is not entirely correct. It is rather than freetype-py did not automatically tidy things up in the right order. So if you have python destructors automatically calling the destructors in c for you, then you may have segfaults when python does not destroy them in the right order; the "fix" at some point in the past was to NOT automatically call c desctructors from python instructors, and just not tidy up at all, and rely on the OS to tidy up on exit of the python script. If you are familiar with freetype enough, you can manually calls the c destructors from freetype-py in the right order within, for long-running freetype-py scripts.

I think it may be a little too much bending over for users' convenience to have automatic tidy up that "works". The c-side is basically library have faces, faces have glyphs, glyphs have bitmaps and outlines, etc. And each of those have "up" references and know what they belong. C users always creates in one direction of order and destroy it from the opposite order.

If you want convenient automatic tidy up to work I.e. you use a whole bunch of faces, find a whole bunch of glyphs, draw a whole bunch of outlines and bitmaps, and then just move on, and hope that freetype-py to tidy them up for you, there will be a whole lot of code on the python side tracking what owns what and what references what. Like if you destroy a face, do you destroy all its associated glyphs and bitmaps now, or do some lazy thing and marked it as deleted but not, and wait until the last glyph/bitmap's with this face is destroyed before actually destroying the face?