Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert static types to heap types: use PyType_FromSpec() #84258

Closed
corona10 opened this issue Mar 26, 2020 · 51 comments
Closed

Convert static types to heap types: use PyType_FromSpec() #84258

corona10 opened this issue Mar 26, 2020 · 51 comments
Labels
3.12 bugs and security fixes extension-modules C modules in the Modules dir type-feature A feature request or enhancement

Comments

@corona10
Copy link
Member

BPO 40077
Nosy @pitrou, @vstinner, @phsilva, @encukou, @skrah, @ericsnowcurrently, @serhiy-storchaka, @corona10, @pablogsal, @miss-islington, @shihai1991, @erlend-aasland, @h-vetinari, @nw0, @kumaraditya303, @CharlieZhao95
PRs
  • bpo-40077: Convert _jsonmodule to use PyType_FromSpec. #19177
  • bpo-40077: Convert _abc module to use PyType_FromSpec() #19202
  • [WIP] bpo-40077: Convert _bz2 extension module to use PyType_FromSpec() #19341
  • bpo-40077: Fix potential refleaks of _json #19344
  • bpo-40077: Remove redundant cast in _json extension module #19438
  • bpo-40077: Convert _bz2 module to use PyType_FromSpec #20960
  • bpo-40077: Convert _csv module to use PyType_FromSpec  #20974
  • bpo-40077: Convert _operaator to use PyType_FromSpec #21953
  • bpo-40077: Convert _operator to use PyType_FromSpec #21954
  • bpo-40077: Convert mmap to use heap types #23108
  • bpo-40077: Convert arraymodule to use heap types and establish module state #23124
  • bpo-40077: Convert _queuemodule to use heap types #23136
  • bpo-40077: Convert _elementtree types to heap types #23428
  • bpo-42327: Add PyModule_Add() (smaller). #23443
  • bpo-40077: Fix typo in simplequeue_get_state_by_type() #23975
  • bpo-40077: Convert itertools types to heap types #24065
  • bpo-40077: Add traverse/clear/free to arraymodule #24066
  • bpo-40077: Convert zoneinfo type to heap type #24481
  • bpo-40077: Convert _pickle module to use heap types. #30884
  • Files
  • bench_isinstance_check.py
  • bench_subclass_check.py
  • bench_isinstance_check.py
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = None
    created_at = <Date 2020-03-26.16:04:44.633>
    labels = ['extension-modules', 'type-feature', '3.10']
    title = 'Convert static types to heap types: use PyType_FromSpec()'
    updated_at = <Date 2022-02-02.05:50:10.693>
    user = 'https://github.com/corona10'

    bugs.python.org fields:

    activity = <Date 2022-02-02.05:50:10.693>
    actor = 'kumaraditya'
    assignee = 'none'
    closed = False
    closed_date = None
    closer = None
    components = ['Extension Modules']
    creation = <Date 2020-03-26.16:04:44.633>
    creator = 'corona10'
    dependencies = []
    files = ['49007', '49008', '49009']
    hgrepos = []
    issue_num = 40077
    keywords = ['patch']
    message_count = 47.0
    messages = ['365087', '365088', '365117', '365125', '365142', '365145', '365149', '365154', '365205', '365220', '365241', '365242', '365255', '365257', '365317', '365558', '365773', '366024', '366061', '368669', '371120', '371813', '371890', '372073', '372074', '372076', '372326', '375943', '380109', '380267', '380516', '380517', '380518', '383848', '383908', '384228', '384236', '384271', '384272', '384293', '410810', '411630', '411903', '411904', '411907', '411964', '412338']
    nosy_count = 16.0
    nosy_names = ['pitrou', 'vstinner', 'phsilva', 'petr.viktorin', 'skrah', 'eric.snow', 'serhiy.storchaka', 'corona10', 'pablogsal', 'miss-islington', 'shihai1991', 'erlendaasland', 'h-vetinari', 'nw0', 'kumaraditya', 'CharlieZhao']
    pr_nums = ['19177', '19202', '19341', '19344', '19438', '20960', '20974', '21953', '21954', '23108', '23124', '23136', '23428', '23443', '23975', '24065', '24066', '24481', '30884']
    priority = 'normal'
    resolution = None
    stage = 'patch review'
    status = 'open'
    superseder = None
    type = 'enhancement'
    url = 'https://bugs.python.org/issue40077'
    versions = ['Python 3.10']

    @corona10
    Copy link
    Member Author

    Some of modules is not using PyType_FromSpec.
    We need to convert them.

    This changes can bring

    • allow to destroy types at exit!
    • allow subinterpreters to have their own "isolated" typ

    @vstinner
    Copy link
    Member

    We need to convert them.

    Let me elaborate. Static types have multiple issues:

    • Their lifetime is not well defined.
    • It is not obvious when they are ready to be used.
    • They are not destroyed at exit.
    • They are incompatible with subinterpreters: each interpreter should have its own copy of a type, rather than static types are shared by all interpreters which cause problems with reference counting (require GIL or atomic operation).
    • They are causing issues with stable ABI (limited C API): PEP-384.

    @pablogsal
    Copy link
    Member

    Wouldn't having less static types slow down startup time?

    @vstinner
    Copy link
    Member

    Pablo:

    Wouldn't having less static types slow down startup time?

    That's possible, even if I only expect a minor or non significant overhead.

    But before starting talking about performances, we should focus on the correctness. Static types are causing issues with subinterpreters and the Python finalization.

    @corona10 corona10 added 3.9 only security fixes topic-C-API labels Mar 27, 2020
    @vstinner
    Copy link
    Member

    New changeset 33f15a1 by Dong-hee Na in branch 'master':
    bpo-40077: Convert _json module to use PyType_FromSpec() (GH-19177)
    33f15a1

    @skrah
    Copy link
    Mannequin

    skrah mannequin commented Mar 27, 2020

    Wouldn't having less static types slow down startup time?

    Yes, and not only startup time:

    https://bugs.python.org/issue15722

    @vstinner
    Copy link
    Member

    In the _json module, PyModule_GetState() (called by get_json_state()) is only used by the garbage collector (traverse function) and to unload the module (clear and free functions). It's not used in "hot code" (let me consider that the GC is not part of the usual "hot code" :-)).

    But maybe we should measure the overhead of future changes if PyModule_GetState() starts to be used in "hot code" by running a few microbenchmarks.

    --

    Stefan Krah:

    Yes, and not only startup time:
    https://bugs.python.org/issue15722

    Aha, that's interesting. I didn't know that it could have an impact on runtime performance as well.

    _decimal_pep3121-384_v1.patch attached to bpo-15722 seems to use:

    #define _decimal_state_global ((_decimal_state *)PyModule_GetState(PyState_FindModule(&_decimal_module)))

    whereas the commit 33f15a1 only uses:

    static inline _jsonmodulestate*
    get_json_state(PyObject *module)
    {
        void *state = PyModule_GetState(module);
        assert(state != NULL);
        return (_jsonmodulestate *)state;
    }

    Maybe PyState_FindModule() adds a little overhead, even if this function is simple: in short, it gets the i-th item of a list (from PyInterpreterState.modules_by_index).

    PyModule_GetState() function is really simple: it only reads PyModuleObject.md_state attribute.

    Or maybe _decimal_state_global was used in "hot code".

    If PyState_FindModule() or PyModule_GetState() is the source of the overhead, maybe we could try to optimise these functions, or pass directly the module state to inner functions.

    --

    PyState_FindModule() doesn't work for a module using PyModuleDef_Init(). The PEP-573 is going to give access to the module state in functions which didn't access to it previsouly.

    The commit 33f15a1 removed a few assertions checking that "self" has the expected type. It wasn't possible to get the module state to get the types, because PEP-573 is not implemented yet and PyState_FindModule() doesn't work in _json (which uses PyModuleDef_Init()). I decided that it's ok to remove these assertions: it should not be possible to call these functions with another type in practice.

    --

    In his PR 19177, Dong-hee started by replacing direct access to PyTypeObject fields, like replacing:

    type->free(self);
    

    with:

    freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
    free_func(self);
    

    I asked him to revert these changes.

    I'm interested to experiment a few C extension modules of the stdlib using the limited C API (PEP-384, stable ABI), but I don't think that it should done while converting modules to PyType_FromSpec().

    We should separate the two changes. And I would prefer to first see the overhead of PyType_FromSpec(), and discuss the advantages and drawbacks.

    @skrah
    Copy link
    Mannequin

    skrah mannequin commented Mar 27, 2020

    Or maybe _decimal_state_global was used in "hot code".

    Yes, _decimal has problems here that most modules don't have.
    Modules like atexit are obviously fine. :)

    I just posted it as an example why one should be a bit cautious.

    The PEP-573 is going to give access to the module state in functions which didn't access to it previously.

    That could help, we'll see.

    @corona10
    Copy link
    Member Author

    And I would prefer to first see the overhead of PyType_FromSpec(), and discuss the advantages and drawbacks.

    Should we stop the work until the overhead is measured?

    @vstinner
    Copy link
    Member

    Should we stop the work until the overhead is measured?

    Can you try to measure the _abc._abc_instancecheck() and _abc._abc_subclasscheck() functions performance before/after your change? Functions like register() are rarely call, so I don't care much of their performance (I expect a small overhead or no overhead).

    @corona10
    Copy link
    Member Author

    It shown 1% slower for performance.

    +--------------------------+-----------------+----------------------------+
    | Benchmark | master-subclass | bpo-40077-subclass |
    +==========================+=================+============================+
    | bench _abc_subclasscheck | 295 ns | 300 ns: 1.01x slower (+1%) |
    +--------------------------+-----------------+----------------------------+

    +--------------------------+-------------------+----------------------------+
    | Benchmark | master-isinstance | bpo-40077-isinstance |
    +==========================+===================+============================+
    | bench _abc_instancecheck | 229 ns | 232 ns: 1.01x slower (+1%) |
    +--------------------------+-------------------+----------------------------+

    @corona10
    Copy link
    Member Author

    Can you try to measure the _abc._abc_instancecheck() and _abc._abc_subclasscheck()

    I 've submitted the benchmark :)

    @vstinner
    Copy link
    Member

    IMO 1.01x slower on a *microbenchmark* is not significant so it's ok. Thanks for checking.

    You pass a *type to isinstance() in bench_isinstance_check.py. You should pass *an instance* instead. Like (complete the (...) ;-)):

    runner.timeit(name="bench _abc_instancecheck",
    stmt="isinstance(obj, T)",
    setup = """from abc import ABC (...) obj = (1, 2, 3)""")

    Would you mind to fix your microbenchmark and re-run it?

    @corona10
    Copy link
    Member Author

    You pass a *type to isinstance() in bench_isinstance_check.py.

    Thanks for the catch my mistake.

    The result is showing:
    Not significant (1): bench _abc_instancecheck

    @vstinner
    Copy link
    Member

    New changeset 53e4c91 by Dong-hee Na in branch 'master':
    bpo-40077: Convert _abc module to use PyType_FromSpec() (GH-19202)
    53e4c91

    @vstinner
    Copy link
    Member

    vstinner commented Apr 2, 2020

    bpo-40077: Convert _abc module to use PyType_FromSpec() (GH-19202)

    This change introduced a reference leak: bpo-40149 "test_threading leaked [38, 38, 38] references, sum=114".

    @vstinner
    Copy link
    Member

    vstinner commented Apr 4, 2020

    New changeset b709302 by Hai Shi in branch 'master':
    bpo-40077: Fix potential refleaks of _json: traverse memo (GH-19344)
    b709302

    @ericsnowcurrently
    Copy link
    Member

    Wouldn't having less static types slow down startup time?

    FWIW, I've been considering an approach where the main interpreter
    keeps using static types but subinterpreters use heap types. If it
    isn't too much effort (or too hacky) then it might be a sufficient
    solution for now.

    @corona10
    Copy link
    Member Author

    corona10 commented Apr 9, 2020

    New changeset dcb04d9 by Hai Shi in branch 'master':
    bpo-40077: Remove redundant cast in json module (GH-19438)
    dcb04d9

    @vstinner
    Copy link
    Member

    See also bpo-40601: [C API] Hide static types from the limited C API.

    @vstinner
    Copy link
    Member

    vstinner commented Jun 9, 2020

    I tried to finalize static types in Py_Finalize(), but it didn't work:

    @vstinner
    Copy link
    Member

    PR 20960 (_bz2 module) triggers an interesting question. The effect of converting a static type to a heap type on pickle, especially for protocols 0 and 1.

    pickle.dumps(o, 0) calls object.__reduce__(o) which calls copyreg._reduce_ex(o, 0).

    copyreg._reduce_ex() behaves differently on heap types:

    ...
    for base in cls.__mro__:
        if hasattr(base, '__flags__') and not base.__flags__ & _HEAPTYPE:
            break
    else:
        base = object # not really reachable
    ...
    

    There are 3 things which impacts serialization/deserialization:

    • Py_TPFLAGS_HEAPTYPE flag in the type flags
    • Is __new__() overriden in the type?
    • Py_TPFLAGS_BASETYPE flag in the type flags

    Examples:

    • In Python 3.7, _random.Random() cannot be serialized because it's a static type (it doesn't have (Py_TPFLAGS_HEAPTYPE)
    • In master, _random.Random() cannot be deserialized because _random.Random() has __new__() method (it's not object.__new__())

    @corona10
    Copy link
    Member Author

    New changeset ec68918 by Dong-hee Na in branch 'master':
    bpo-40077: Convert _bz2 module to use PyType_FromSpec (GH-20960)
    ec68918

    @vstinner
    Copy link
    Member

    Progress: 43% (89/206) of types are declared as heap types on a total of 206 types.

    $ grep -E 'static PyTypeObject .* =' $(find -name "*.c"|grep -v Doc/)|wc -l
    117
    $ grep -E 'PyType_Spec .* =' $(find -name "*.c")|wc -l
    89

    @miss-islington
    Copy link
    Contributor

    New changeset bf108bb by Erlend Egeberg Aasland in branch 'master':
    bpo-40077: Fix typo in simplequeue_get_state_by_type() (GH-23975)
    bf108bb

    @encukou
    Copy link
    Member

    encukou commented Jan 2, 2021

    New changeset 75bf107 by Erlend Egeberg Aasland in branch 'master':
    bpo-40077: Convert arraymodule to use heap types and establish module state (GH-23124)
    75bf107

    @erlend-aasland
    Copy link
    Contributor

    Should Modules/_testcapimodule.c stay untouched?

    @encukou
    Copy link
    Member

    encukou commented Jan 3, 2021

    New changeset b8eb376 by Erlend Egeberg Aasland in branch 'master':
    bpo-40077: Add traverse/clear/free to arraymodule (GH-24066)
    b8eb376

    @encukou
    Copy link
    Member

    encukou commented Jan 3, 2021

    Yes, please keep _testcapimodule.c as it is. Static types are still supported and need to be tested.

    @erlend-aasland
    Copy link
    Contributor

    Ok, perhaps we should leave a comment about that? It already has a comment about multi-phase init.

    What about Modules/_testbuffer.c and the xx-modules?

    $ grep -E 'static PyTypeObject .* =' $(find . -name "*.c"|grep -vE '(Doc/|Modules/_testcapimodule)') | wc -l
    94
    
    $ grep -E 'PyType_Spec .* =' $(find . -name "*.c")|wc -l                                                                                                                            (master)cpython.git
    95

    We're almost halfway there.

    @vstinner
    Copy link
    Member

    See also bpo-46417 "[subinterpreters] Clear static types in Py_Finalize()".

    @vstinner
    Copy link
    Member

    Converting further static types to heap types require a discussion. See what the Python Steering Council wrote at Feb 8, 2021:

    "The Steering Council discussed the ongoing work on porting types in the standard library to heap-types and the subinterpreter-related changes. It was decided that through Pablo, the Steering Council will ask the core developers driving those changes to create an informational PEP and not to make any more changes in this area after beta 1, as per our general policy."

    https://github.com/python/steering-council/blob/1d85eefdc5861a096c3859e9990dbc8527c5973b/updates/2021-02-steering-council-update.md

    @vstinner
    Copy link
    Member

    I used the following shell command to search remaining static types:
    ---
    grep -E 'static PyTypeObject [a-zA-Z_0-9]+ *(;|= *{|) *$' $(find -name "*.c")
    ---

    I found 86 static types in 17 files:

    @vstinner
    Copy link
    Member

    And I found 135 more static types with this command:
    ---
    grep -E '^PyTypeObject [a-zA-Z_0-9]+ *(;|= *{|) *$' $(find -name "*.c")
    ---

    Types:

    Objects/cellobject.c: PyCell_Type
    Objects/sliceobject.c: PyEllipsis_Type
    Objects/sliceobject.c: PySlice_Type
    Objects/unionobject.c: _PyUnion_Type
    Objects/methodobject.c: PyCFunction_Type
    Objects/methodobject.c: PyCMethod_Type
    Objects/picklebufobject.c: PyPickleBuffer_Type
    Objects/boolobject.c: PyBool_Type
    Objects/bytearrayobject.c: PyByteArray_Type
    Objects/bytearrayobject.c: PyByteArrayIter_Type
    Objects/classobject.c: PyMethod_Type
    Objects/classobject.c: PyInstanceMethod_Type
    Objects/fileobject.c: PyStdPrinter_Type
    Objects/genericaliasobject.c: Py_GenericAliasType
    Objects/interpreteridobject.c: _PyInterpreterID_Type
    Objects/iterobject.c: PySeqIter_Type
    Objects/iterobject.c: PyCallIter_Type
    Objects/iterobject.c: _PyAnextAwaitable_Type
    Objects/moduleobject.c: PyModuleDef_Type
    Objects/moduleobject.c: PyModule_Type
    Objects/rangeobject.c: PyRange_Type
    Objects/rangeobject.c: PyRangeIter_Type
    Objects/rangeobject.c: PyLongRangeIter_Type
    Objects/namespaceobject.c: _PyNamespace_Type
    Objects/bytesobject.c: PyBytes_Type
    Objects/bytesobject.c: PyBytesIter_Type
    Objects/capsule.c: PyCapsule_Type
    Objects/complexobject.c: PyComplex_Type
    Objects/dictobject.c: PyDict_Type
    Objects/dictobject.c: PyDictIterKey_Type
    Objects/dictobject.c: PyDictIterValue_Type
    Objects/dictobject.c: PyDictIterItem_Type
    Objects/dictobject.c: PyDictRevIterKey_Type
    Objects/dictobject.c: PyDictRevIterItem_Type
    Objects/dictobject.c: PyDictRevIterValue_Type
    Objects/dictobject.c: PyDictKeys_Type
    Objects/dictobject.c: PyDictItems_Type
    Objects/dictobject.c: PyDictValues_Type
    Objects/floatobject.c: PyFloat_Type
    Objects/frameobject.c: PyFrame_Type
    Objects/funcobject.c: PyFunction_Type
    Objects/funcobject.c: PyClassMethod_Type
    Objects/funcobject.c: PyStaticMethod_Type
    Objects/memoryobject.c: _PyManagedBuffer_Type
    Objects/memoryobject.c: PyMemoryView_Type
    Objects/odictobject.c: PyODict_Type
    Objects/odictobject.c: PyODictIter_Type
    Objects/odictobject.c: PyODictKeys_Type
    Objects/odictobject.c: PyODictItems_Type
    Objects/odictobject.c: PyODictValues_Type
    Objects/setobject.c: PySetIter_Type
    Objects/setobject.c: PySet_Type
    Objects/setobject.c: PyFrozenSet_Type
    Objects/setobject.c: _PySetDummy_Type
    Objects/tupleobject.c: PyTuple_Type
    Objects/tupleobject.c: PyTupleIter_Type
    Objects/object.c: _PyNone_Type
    Objects/object.c: _PyNotImplemented_Type
    Objects/unicodeobject.c: PyUnicode_Type
    Objects/unicodeobject.c: PyUnicodeIter_Type
    Objects/listobject.c: PyList_Type
    Objects/listobject.c: PyListIter_Type
    Objects/listobject.c: PyListRevIter_Type
    Objects/genobject.c: PyGen_Type
    Objects/genobject.c: PyCoro_Type
    Objects/genobject.c: _PyCoroWrapper_Type
    Objects/genobject.c: PyAsyncGen_Type
    Objects/genobject.c: _PyAsyncGenASend_Type
    Objects/genobject.c: _PyAsyncGenWrappedValue_Type
    Objects/genobject.c: _PyAsyncGenAThrow_Type
    Objects/longobject.c: PyLong_Type
    Objects/descrobject.c: PyMethodDescr_Type
    Objects/descrobject.c: PyClassMethodDescr_Type
    Objects/descrobject.c: PyMemberDescr_Type
    Objects/descrobject.c: PyGetSetDescr_Type
    Objects/descrobject.c: PyWrapperDescr_Type
    Objects/descrobject.c: _PyMethodWrapper_Type
    Objects/descrobject.c: PyDictProxy_Type
    Objects/descrobject.c: PyProperty_Type
    Objects/enumobject.c: PyEnum_Type
    Objects/enumobject.c: PyReversed_Type
    Objects/codeobject.c: _LineIterator
    Objects/codeobject.c: _PositionsIterator
    Objects/codeobject.c: PyCode_Type
    Objects/typeobject.c: PyType_Type
    Objects/typeobject.c: PyBaseObject_Type
    Objects/typeobject.c: PySuper_Type
    Python/bltinmodule.c: PyFilter_Type
    Python/bltinmodule.c: PyMap_Type
    Python/bltinmodule.c: PyZip_Type
    Python/context.c: PyContext_Type
    Python/context.c: PyContextVar_Type
    Python/context.c: PyContextToken_Type
    Python/context.c: _PyContextTokenMissing_Type
    Python/hamt.c: _PyHamtItems_Type
    Python/hamt.c: _PyHamtKeys_Type
    Python/hamt.c: _PyHamtValues_Type
    Python/hamt.c: _PyHamt_Type
    Python/hamt.c: _PyHamt_ArrayNode_Type
    Python/hamt.c: _PyHamt_BitmapNode_Type
    Python/hamt.c: _PyHamt_CollisionNode_Type
    Python/traceback.c: PyTraceBack_Type
    Python/symtable.c: PySTEntry_Type
    Modules/_ctypes/callproc.c: PyCArg_Type
    Modules/_ctypes/_ctypes.c: PyCStructType_Type
    Modules/_ctypes/_ctypes.c: PyCPointerType_Type
    Modules/_ctypes/_ctypes.c: PyCArrayType_Type
    Modules/_ctypes/_ctypes.c: PyCSimpleType_Type
    Modules/_ctypes/_ctypes.c: PyCFuncPtrType_Type
    Modules/_ctypes/_ctypes.c: PyCData_Type
    Modules/_ctypes/_ctypes.c: PyCFuncPtr_Type
    Modules/_ctypes/_ctypes.c: PyCArray_Type
    Modules/_ctypes/_ctypes.c: PyCPointer_Type
    Modules/_ctypes/cfield.c: PyCField_Type
    Modules/_ctypes/stgdict.c: PyCStgDict_Type
    Modules/_ctypes/callbacks.c: PyCThunk_Type
    Modules/_io/iobase.c: PyIOBase_Type
    Modules/_io/iobase.c: PyRawIOBase_Type
    Modules/_io/stringio.c: PyStringIO_Type
    Modules/_io/textio.c: PyTextIOBase_Type
    Modules/_io/textio.c: PyIncrementalNewlineDecoder_Type
    Modules/_io/textio.c: PyTextIOWrapper_Type
    Modules/_io/bytesio.c: PyBytesIO_Type
    Modules/_io/fileio.c: PyFileIO_Type;
    Modules/_io/fileio.c: PyFileIO_Type
    Modules/_io/winconsoleio.c: PyWindowsConsoleIO_Type;
    Modules/_io/winconsoleio.c: PyWindowsConsoleIO_Type
    Modules/_io/bufferedio.c: PyBufferedIOBase_Type
    Modules/_io/bufferedio.c: PyBufferedReader_Type
    Modules/_io/bufferedio.c: PyBufferedWriter_Type
    Modules/_io/bufferedio.c: PyBufferedRWPair_Type
    Modules/_io/bufferedio.c: PyBufferedRandom_Type
    Modules/_multiprocessing/semaphore.c: _PyMp_SemLockType
    Modules/_cursesmodule.c: PyCursesWindow_Type;
    Modules/_cursesmodule.c: PyCursesWindow_Type

    @vstinner
    Copy link
    Member

    And I found 135 more static types with this command

    Of these 135 static types, most are cleared since bpo-46417 was implemented:

    • 103 types are cleared by _PyTypes_FiniTypes()
    • 15 types are cleared by _PyIO_Fini()
    • the remaining 17 types are not cleared at Python exit: types of _ctypes, _curses and _multiprocessing extensions

    @vstinner
    Copy link
    Member

    I marked bpo-23769 "valgrind reports leaks for test_zipimport" as duplicate of this issue. At exit, Python doesn't clear the static types of the _collections, itertools and _struct extensions:

    • itertools.accumulate
    • itertools.combinations
    • itertools.combinations_with_replacement
    • itertools.cycle
    • itertools.dropwhile
    • itertools.takewhile
    • itertools.islice
    • itertools.starmap
    • itertools.chain
    • itertools.compress
    • itertools.filterfalse
    • itertools.count
    • itertools.zip_longest
    • itertools.pairwise
    • itertools.permutations
    • itertools.product
    • itertools.repeat
    • itertools.groupby
    • itertools._grouper
    • itertools._tee
    • itertools._tee_dataobject
    • collections.deque
    • _collections._deque_iterator
    • _collections._deque_reverse_iterator
    • _collections._tuplegetter
    • _struct.Struct
    • _struct.unpack_iterator

    See: https://bugs.python.org/issue23769#msg411963

    @kumaraditya303
    Copy link
    Contributor

    On Windows PC/winreg.c has PyHKEY_Type static type which isn't cleared at exit too.

    @kumaraditya303
    Copy link
    Contributor

    PEP 687 was accepted

    @kumaraditya303 kumaraditya303 added 3.12 bugs and security fixes and removed 3.10 only security fixes labels Jun 27, 2022
    @erlend-aasland
    Copy link
    Contributor

    erlend-aasland commented Jun 27, 2022

    PEP 687 was accepted

    Note that this does not imply that all types shall be converted to heap types. This is also mentioned in the PEP; please read it carefully.

    @kumaraditya303
    Copy link
    Contributor

    Note that this does not imply that all types shall be converted to heap types. This is also mentioned in the PEP; please read it carefully.

    We are on the same page, every module needs to considered individually and I am against converting any built-in modules or types unless it's necessary.

    @kumaraditya303
    Copy link
    Contributor

    Superseded by #103092

    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    3.12 bugs and security fixes extension-modules C modules in the Modules dir type-feature A feature request or enhancement
    Projects
    None yet
    Development

    No branches or pull requests

    10 participants