Giter Club home page Giter Club logo

Comments (10)

HinTak avatar HinTak commented on September 21, 2024

Argh, I thought this has been discussed before, and it has:
#44

from freetype-py.

HinTak avatar HinTak commented on September 21, 2024

This can be a good task to learn about freetype. This can be investigated by building a debug version of freetype, set FT_DEBUG / FT_TRACE to see when and what freetype receives from freetype-py from the other side. This could fix some of the other issues with other __del__ too.

At the moment we don't do anything in a few of __del__ , since they don't work correctly, but it leaks a bit after repeat usages.

from freetype-py.

carandraug avatar carandraug commented on September 21, 2024

I've been seeing reports for this error for a couple of years now microscope-cockpit/cockpit#684 (it's always when the program is exiting so we never paid much attention).

Effectively, the error is at https://github.com/rougier/freetype-py/blob/ccd4f5fca0fb1dd69e40b2966db60139ec1c49da/freetype/__init__.py#LL1231C1-L1231C42 , i.e.:

        FT_Done_Face( self._FT_Face )

And what is None is FT_Done_Face. I guess this means that __del__ is being called after ctypes having dlclosed the shared library.

from freetype-py.

carandraug avatar carandraug commented on September 21, 2024

I tried to look deeper into this and even freetype (the Python module) is already None at this point. It appears that it all boils down to this warning in Python's documentation:

Warning: Due to the precarious circumstances under which del() methods are invoked, exceptions that occur during their execution are ignored, and a warning is printed to sys.stderr instead. In particular:

  • del() can be invoked when arbitrary code is being executed, including from any arbitrary thread. If del() needs to take a lock or invoke any other blocking resource, it may deadlock as the resource may already be taken by the code that gets interrupted to execute del().

  • del() can be executed during interpreter shutdown. As a consequence, the global variables it needs to access (including other modules) may already have been deleted or set to None. Python guarantees that globals whose name begins with a single underscore are deleted from their module before other globals are deleted; if no other references to such globals exist, this may help in assuring that imported modules are still available at the time when the del() method is called.

There's stackoverflow questions and python bug reports about this (here's a similar Python bug report). Recommendation from Python itself seems to get a strong reference to the needed machinery before trying to use. I will open a pull request.

from freetype-py.

HinTak avatar HinTak commented on September 21, 2024

That is nonsense. FT_Done_Face() is a binding of the shared library.

What is quite likely is that FT_Done_Library() (which also calls FT_Done_Face() on the library side) is occasionally called automatically first before FT_Done_Face() by ctypes. The del face method probably should check the library handle and that FT_Done_Library() has not been called yet.

Edit: hmm, on 2nd thought. I think it is really best to investigate with a debug build of freetype.

from freetype-py.

HinTak avatar HinTak commented on September 21, 2024

Sorry, on another thought, since freetype itself hasn't segfaulted, the problem is entirely on the python side. There is the ctype object which holds the reference to the shares library, and the library pointer returned from FT_Init_Library(), both of these could go before the face object.

from freetype-py.

carandraug avatar carandraug commented on September 21, 2024

This is the testing I did that shows the issue. This is the diff:

diff --git a/freetype/__init__.py b/freetype/__init__.py
index 4b65985..0b749ee 100644
--- a/freetype/__init__.py
+++ b/freetype/__init__.py
@@ -21,6 +21,7 @@ from ctypes import *
 import ctypes.util
 import struct
 
+import freetype.raw
 from freetype.raw import *
 
 # Hack to get unicode class in python3
@@ -1227,6 +1228,9 @@ class Face( object ):
         '''
         Discard  face object, as well as all of its child slots and sizes.
         '''
+        print("is FT_Done_Face None", FT_Done_Face is None)
+        print("is freetype None", freetype is None)
+        print("does freetype.raw exist", hasattr(freetype, "raw"))
         if self._FT_Face is not None:
             FT_Done_Face( self._FT_Face )
 

and this is the output:

is FT_Done_Face None True
is freetype None True
does freetype.raw exist False
Exception ignored in: <function Face.__del__ at 0x00000167919035B0>
Traceback (most recent call last):
  File "C:\Users\vgg\AppData\Roaming\Python\Python310\site-packages\freetype\__init__.py", line 1235, in __del__
TypeError: 'NoneType' object is not callable

The error message is also clear. What is being called is FT_Done_Face and the issue is that None is not callable.

This shows that the problem is that FT_Done_Face has been set to None and I guess that this is happening because, as described in Python docs, the interpreting is shutting down and "the global variables [__del__] needs to access (including other modules) may already have been deleted or set to None."

from freetype-py.

HinTak avatar HinTak commented on September 21, 2024

We probably need the case where FT_Done_Face is called. Otherwise it isn't better than simply deleting those lines.

from freetype-py.

carandraug avatar carandraug commented on September 21, 2024

We probably need the case where FT_Done_Face is called. Otherwise it isn't better than simply deleting those lines.

In the case where FT_Done_Face is called, with the patch above, this is the output (basically, there is no issue because FT_Done_Face has not yet been set to None):

is FT_Done_Face None False
is freetype None False
does freetype.raw exist True

from freetype-py.

carandraug avatar carandraug commented on September 21, 2024

With the pull request #171 this issue is fixed.

There may be other issues with cleanup during runtime but the specific issue described here, i.e., "on exit, freetype/init.py", line 1233, in del TypeError: 'NoneType' object is not callable", is specific to "faces" during shutdown.

from freetype-py.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.