STINNER Victor <vstin...@python.org> added the comment:
Hum, some clarification is needed here. "Port xxx extension module to multiphase initialization (PEP 489)" changes are helping to fix "Py_Finalize() doesn't clear all Python objects at exit", but alone they don't fix all issues. -- For example, if a module still uses globals using "static ..." in C, these globals will not be cleared magically. Example with _datetimemodule.c: static PyObject *us_per_hour = NULL; /* 1e6 * 3600 as Python int */ static PyObject *us_per_day = NULL; /* 1e6 * 3600 * 24 as Python int */ static PyObject *us_per_week = NULL; /* 1e6*3600*24*7 as Python int */ These variables initialized once in PyInit__datetime(): us_per_hour = PyLong_FromDouble(3600000000.0); us_per_day = PyLong_FromDouble(86400000000.0); us_per_week = PyLong_FromDouble(604800000000.0); Converting the module to multiphase initialization will not magically clear these variables at exit. The _datetime module should be modified to store these variables in a module state: this module could be cleared at exit. The binascii is a good example: it has a module state, traverse, clear and free methods, and it uses the multiphase initialization. This module can be fully unloaded at exit. It's a "simple" module: it doesn't define types for example. -- Another issue is that converting a module to the multiphase initialization doesn't magically fully isolate two instances of the module. For exmaple, the _abc module still uses a type defined statically: static PyTypeObject _abc_data_type = { PyVarObject_HEAD_INIT(NULL, 0) "_abc_data", /*tp_name*/ sizeof(_abc_data), /*tp_basicsize*/ .tp_dealloc = (destructor)abc_data_dealloc, .tp_flags = Py_TPFLAGS_DEFAULT, .tp_alloc = PyType_GenericAlloc, .tp_new = abc_data_new, }; Example: vstinner@apu$ ./python Python 3.9.0a5+ (heads/pr/19122:0ac3031a80, Mar 25 2020, 02:25:19) >>> import _abc >>> class Bla: pass ... >>> _abc._abc_init(Bla) >>> type(Bla._abc_impl) <class '_abc_data'> # load a second instance of the module >>> import sys; del sys.modules['_abc'] >>> import _abc as _abc2 >>> class Bla2: pass ... >>> _abc._abc_init(Bla2) >>> type(Bla2._abc_impl) <class '_abc_data'> # _abc and _abc2 have exactly the same type, # they are not fully isolated >>> type(Bla2._abc_impl) is type(Bla._abc_impl) True That's more an issue for subinterpreters: each interpreter should have its own fully isolated instance of an C extension module. ---------- _______________________________________ Python tracker <rep...@bugs.python.org> <https://bugs.python.org/issue1635741> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com