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

Clear static types in Py_Finalize() for embedded Python #90575

Closed
vstinner opened this issue Jan 17, 2022 · 50 comments
Closed

Clear static types in Py_Finalize() for embedded Python #90575

vstinner opened this issue Jan 17, 2022 · 50 comments
Labels
3.11 only security fixes interpreter-core (Objects, Python, Grammar, and Parser dirs)

Comments

@vstinner
Copy link
Member

BPO 46417
Nosy @vstinner, @phsilva, @encukou, @corona10, @miss-islington, @shihai1991, @erlend-aasland, @kumaraditya303
PRs
  • bpo-46417: Finalize structseq types at exit #30645
  • bpo-46417: _testembed.c avoids Py_SetProgramName() #30732
  • bpo-46417: _thread module uses PyStructSequence_NewType() #30733
  • bpo-46417: time module uses PyStructSequence_NewType() #30734
  • bpo-46417: signal uses PyStructSequence_NewType() #30735
  • bpo-46417: _curses uses PyStructSequence_NewType() #30736
  • bpo-46417: Py_Finalize() clears static types #30743
  • bpo-46417: Call _PyDebug_PrintTotalRefs() later #30744
  • bpo-46417: Add missing types of _PyTypes_InitTypes() #30749
  • bpo-46417: Revert remove_subclass() change #30750
  • bpo-46417: Add _PyType_CAST() macro #30760
  • bpo-46417: Add _PyType_GetSubclasses() function #30761
  • bpo-46417: PyWeakref_GET_OBJECT() uses PyWeakref_CheckRef() #30763
  • bpo-46417: Use _PyType_CAST() in Objects directory #30764
  • bpo-46417: Use _PyType_CAST() in Python directory #30769
  • bpo-46417: Use _PyType_CAST() in Modules directory #30767
  • bpo-46417: Fix type recurse_down_subclasses() #30775
  • bpo-46417: Fix race condition on setting type __bases__ #30788
  • [3.10] bpo-46417: Fix race condition on setting type __bases__ (GH-30788) #30789
  • [3.9] bpo-46417: Fix race condition on setting type __bases__ (GH-30788) #30790
  • bpo-46417: Debug tp_subclasses crash #30791
  • bpo-46417: remove_subclass() clears tp_subclasses #30793
  • bpo-46417: Cleanup typeobject.c code #30795
  • bpo-46417: Clear more static types #30796
  • bpo-46417: _PyTypes_FiniTypes() clears object and type #30798
  • bpo-46417: Cleanup _PyExc_InitTypes() #30804
  • bpo-46417: Py_Finalize() clears static exceptioins #30805
  • bpo-46417: Clear Unicode static types at exit #30806
  • bpo-46417: Clear _io module static objects at exit #30807
  • bpo-46417: Clear symtable identifiers at exit #30809
  • bpo-46417: Fix _PyStaticType_Dealloc() #30810
  • bpo-46417: _PyList_Fini() clears indexerr #30815
  • bpo-46417: signal: move siginfo_type to the module state #30964
  • bpo-46417: _PyStructSequence_FiniType() updates _Py_RefTotal #30988
  • Files
  • cannot_deallocate.patch
  • cannot_deallocate2.patch
  • 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 = <Date 2022-01-27.20:22:54.970>
    created_at = <Date 2022-01-17.17:19:20.743>
    labels = ['interpreter-core', '3.11']
    title = 'Clear static types in Py_Finalize() for embedded Python'
    updated_at = <Date 2022-01-28.13:08:43.043>
    user = 'https://github.com/vstinner'

    bugs.python.org fields:

    activity = <Date 2022-01-28.13:08:43.043>
    actor = 'vstinner'
    assignee = 'none'
    closed = True
    closed_date = <Date 2022-01-27.20:22:54.970>
    closer = 'vstinner'
    components = ['Interpreter Core']
    creation = <Date 2022-01-17.17:19:20.743>
    creator = 'vstinner'
    dependencies = []
    files = ['50576', '50577']
    hgrepos = []
    issue_num = 46417
    keywords = ['patch']
    message_count = 50.0
    messages = ['410808', '410858', '410866', '411025', '411033', '411049', '411063', '411064', '411066', '411070', '411071', '411073', '411076', '411077', '411117', '411118', '411122', '411127', '411139', '411143', '411148', '411182', '411201', '411202', '411203', '411232', '411255', '411256', '411257', '411263', '411271', '411272', '411275', '411276', '411281', '411290', '411291', '411292', '411296', '411300', '411303', '411304', '411305', '411307', '411317', '411329', '411332', '411917', '411918', '411994']
    nosy_count = 8.0
    nosy_names = ['vstinner', 'phsilva', 'petr.viktorin', 'corona10', 'miss-islington', 'shihai1991', 'erlendaasland', 'kumaraditya']
    pr_nums = ['30645', '30732', '30733', '30734', '30735', '30736', '30743', '30744', '30749', '30750', '30760', '30761', '30763', '30764', '30769', '30767', '30775', '30788', '30789', '30790', '30791', '30793', '30795', '30796', '30798', '30804', '30805', '30806', '30807', '30809', '30810', '30815', '30964', '30988']
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = None
    url = 'https://bugs.python.org/issue46417'
    versions = ['Python 3.11']

    @vstinner
    Copy link
    Member Author

    Converting static types to heap types is a work-in-progress:

    • bpo-40077: "Convert static types to heap types: use PyType_FromSpec()"
    • At December 29, 2020, 43% (89/206) of types are declared as heap types on a total of 206 types. For comparison, in Python 3.8, only 9% (15/172) of types were declared as heap types: 74 types have been converted in the meanwhile.
    • https://vstinner.github.io/isolate-subinterpreters.html

    Static types are still causing issues with Py_Initialize() / Py_Finalize() is called multiple times in the same process, which is a supported use case for embedded Python. See bpo-45691 "Partial moving of core objects to interpreter state is incorrect at best, unsafe at worse" for a recent example with sys.float_info where sys.float_info.n_unnamed_fields holds a reference to a Python object.

    In june 2020, I wrote #64962 to clear static types at exit. But I abandoned my attempt because of bugs. Copy of my https://bugs.python.org/issue1635741#msg371119 message:

    """
    I wrote PR 20763 to "finalize" static types in Py_Finalize(). It mostly works, but "./Programs/_testembed test_forced_io_encoding" crash. This program calls Py_Initialize() and Py_Finalize() multiple times in a loop.

    It doesn't look to be safe to clear static types. Many functions rely on the fact that static types are "always there" and are never finalized. Also, only a few static types are cleared by my PR: many static types are left unchanged. For example, static types of the _io module.

    It seems like a safer approach is to continue the work on bpo-40077: "Convert static types to PyType_FromSpec()".
    """

    I propose a "best effort" approach: only clear a static type if it is no longer used. For example, check its reference count and its __subclasses__() method.

    @vstinner vstinner added topic-subinterpreters 3.11 only security fixes labels Jan 17, 2022
    @encukou
    Copy link
    Member

    encukou commented Jan 18, 2022

    If we have static types, that means there is a mechanism to share some objects across interpreters.
    And if that's the case, why can't small ints (like sys.float_info.n_unnamed_fields) be static & shared as well?

    @vstinner
    Copy link
    Member Author

    If we have static types, that means there is a mechanism to share some objects across interpreters.

    Sharing objects between interpreters is bad and is causing complex bugs. See a recent example of an object traveling from one interpreter to another and then causing a random crash on Windows related to the garbage collector:

    And if that's the case, why can't small ints (like sys.float_info.n_unnamed_fields) be static & shared as well?

    I would prefer to discuss that in other issues like bpo-40255 or bpo-39511, and focus this issue on fixing the static types implementation when Python is embedded in an application.

    --

    Hum, this issue is not really related to sub-interpreters. My proposed PR only changes Py_Finalize(): the main interpreter.

    @vstinner vstinner changed the title [subinterpreters] Clear static types in Py_Finalize() Clear static types in Py_Finalize() for embedded Python Jan 18, 2022
    @vstinner vstinner changed the title [subinterpreters] Clear static types in Py_Finalize() Clear static types in Py_Finalize() for embedded Python Jan 18, 2022
    @vstinner vstinner added interpreter-core (Objects, Python, Grammar, and Parser dirs) and removed topic-subinterpreters labels Jan 18, 2022
    @encukou
    Copy link
    Member

    encukou commented Jan 20, 2022

    Sharing objects between interpreters is bad

    That's your opinion, I don't necessarily share it.

    and is causing complex bugs.

    But converting static things (types, small ints) to heap is also causing bugs :(

    ----

    Anyway, for this issue: is there a way to test if the types are correctly reinitialized if there are multiple finalize/init cycles?
    I worry about introducing more unexpected issues here.

    @vstinner
    Copy link
    Member Author

    If tomorrow static types are shared between sub-interpreters, it doesn't solve this problem: we still need to release memory allocated by Py_Initialize() in Py_Finalize() when Python is embedded. This issue is a sub-set of the big bpo-1635741 which explains the rationale. Again, this issue is not about sub-interpreters.

    Anyway, for this issue: is there a way to test if the types are correctly reinitialized if there are multiple finalize/init cycles? I worry about introducing more unexpected issues here.

    I wasn't sure how to test it. But well, Dong-hee and you asked for tests, so I added tests for my PR ;-)

    @vstinner
    Copy link
    Member Author

    I checked with Valgrind the affect of PR 30645.

    main branch:

    ==330902== LEAK SUMMARY:
    ==330902== possibly lost: 29,128 bytes in 494 blocks
    ==330902== still reachable: 353,615 bytes in 3,577 blocks

    With the PR:

    ==332161== LEAK SUMMARY:
    ==332161== possibly lost: 24,456 bytes in 417 blocks
    ==332161== still reachable: 337,223 bytes in 3,423 blocks

    It frees 21,064 bytes (20 kB) in Py_Finalize().

    @vstinner
    Copy link
    Member Author

    Another measure using the command:

        PYTHONHASHSEED=0 ./python -X showrefcount -c pass

    I had to run the command 20 times to get a stable value, I don't know why.

    main branch: [21981 refs, 5716 blocks]
    PR: [21887 refs, 5667 blocks]

    => the PR removes 94 references and 49 memory blocks.

    @vstinner
    Copy link
    Member Author

    New changeset e9e3eab by Victor Stinner in branch 'main':
    bpo-46417: Finalize structseq types at exit (GH-30645)
    e9e3eab

    @vstinner
    Copy link
    Member Author

    New changeset 6415e2e by Victor Stinner in branch 'main':
    bpo-46417: _testembed.c avoids Py_SetProgramName() (GH-30732)
    6415e2e

    @vstinner
    Copy link
    Member Author

    New changeset f389b37 by Victor Stinner in branch 'main':
    bpo-46417: _thread uses PyStructSequence_NewType() (GH-30733)
    f389b37

    @vstinner
    Copy link
    Member Author

    New changeset 17f268a by Victor Stinner in branch 'main':
    bpo-46417: time module uses PyStructSequence_NewType() (GH-30734)
    17f268a

    @vstinner
    Copy link
    Member Author

    New changeset 1781d55 by Victor Stinner in branch 'main':
    bpo-46417: _curses uses PyStructSequence_NewType() (GH-30736)
    1781d55

    @vstinner
    Copy link
    Member Author

    See also bpo-46449 "Deep-freezed modules create inconsistency in sys.gettotalrefcount() (_Py_Reftotal)".

    @vstinner
    Copy link
    Member Author

    New changeset d013b24 by Victor Stinner in branch 'main':
    bpo-46417: signal uses PyStructSequence_NewType() (GH-30735)
    d013b24

    @vstinner
    Copy link
    Member Author

    New changeset ea38e43 by Victor Stinner in branch 'main':
    bpo-46417: Call _PyDebug_PrintTotalRefs() later (GH-30744)
    ea38e43

    @vstinner
    Copy link
    Member Author

    New changeset 595225e by Victor Stinner in branch 'main':
    bpo-46417: Py_Finalize() clears static types (GH-30743)
    595225e

    @vstinner
    Copy link
    Member Author

    bpo-46417: Py_Finalize() clears static types (GH-30743)

    Oh, test_unittest crashed on s390x Debian 3.x:
    https://buildbot.python.org/all/#/builders/49/builds/1789

    I fail to see the relationship between my change and this crash. I don't expect test_unittest to call Py_Finalize() and then Py_Initialize() again.

    ---
    0:01:32 load avg: 4.77 [152/432/1] test_unittest crashed (Exit code -11) -- running: test_peg_generator (48.3 sec)
    Fatal Python error: Segmentation fault

    Current thread 0x000003ff89cf8720 (most recent call first):
    File "/home/dje/cpython-buildarea/3.x.edelsohn-debian-z/build/Lib/inspect.py", line 2179 in _signature_fromstr
    File "/home/dje/cpython-buildarea/3.x.edelsohn-debian-z/build/Lib/inspect.py", line 2273 in _signature_from_builtin
    File "/home/dje/cpython-buildarea/3.x.edelsohn-debian-z/build/Lib/inspect.py", line 2461 in _signature_from_callable
    File "/home/dje/cpython-buildarea/3.x.edelsohn-debian-z/build/Lib/inspect.py", line 2465 in _signature_from_callable
    File "/home/dje/cpython-buildarea/3.x.edelsohn-debian-z/build/Lib/inspect.py", line 2966 in from_callable
    File "/home/dje/cpython-buildarea/3.x.edelsohn-debian-z/build/Lib/inspect.py", line 3218 in signature
    File "/home/dje/cpython-buildarea/3.x.edelsohn-debian-z/build/Lib/unittest/mock.py", line 112 in _get_signature_object
    File "/home/dje/cpython-buildarea/3.x.edelsohn-debian-z/build/Lib/unittest/mock.py", line 505 in _mock_add_spec
    File "/home/dje/cpython-buildarea/3.x.edelsohn-debian-z/build/Lib/unittest/mock.py", line 487 in mock_add_spec
    File "/home/dje/cpython-buildarea/3.x.edelsohn-debian-z/build/Lib/unittest/test/testmock/testmock.py", line 1767 in test_mock_add_spec
    File "/home/dje/cpython-buildarea/3.x.edelsohn-debian-z/build/Lib/unittest/case.py", line 547 in _callTestMethod
    (...)
    File "/home/dje/cpython-buildarea/3.x.edelsohn-debian-z/build/Lib/test/regrtest.py", line 47 in <module>
    File "<frozen runpy>", line 88 in _run_code
    File "<frozen runpy>", line 198 in _run_module_as_main

    Extension modules: _testcapi (total: 1)
    ---

    @vstinner
    Copy link
    Member Author

    Maybe the problem is that I changed the order in which types are initialized in _PyTypes_InitTypes()?

    So far, test_unittest crashed on 4 buildbot workers:

    • s390x Debian 3.x: ./configure --prefix '$(PWD)/target' --with-pydebug
      https://buildbot.python.org/all/#/builders/49/builds/1789

    • aarch64 Fedora Stable 3.x: ../configure --prefix '$(PWD)/target' --with-pydebug --with-platlibdir=lib64 --enable-ipv6 --enable-shared --with-computed-gotos=yes --with-dbmliborder=gdbm:ndbm:bdb --enable-loadable-sqlite-extensions --with-ssl-default-suites=openssl --without-static-libpython --with-lto
      https://buildbot.python.org/all/#/builders/125/builds/1263

    • aarch64 RHEL8 3.x: ../configure --prefix '$(PWD)/target' --with-pydebug --with-platlibdir=lib64 --enable-ipv6 --enable-shared --with-computed-gotos=yes --with-dbmliborder=gdbm:ndbm:bdb --enable-loadable-sqlite-extensions --with-ssl-default-suites=openssl --without-static-libpython --with-lto
      https://buildbot.python.org/all/#/builders/529/builds/1357

    • PPC64LE RHEL8 3.x: ../configure --prefix '$(PWD)/target' --with-pydebug --with-platlibdir=lib64 --enable-ipv6 --enable-shared --with-computed-gotos=yes --with-dbmliborder=gdbm:ndbm:bdb --enable-loadable-sqlite-extensions --with-ssl-default-suites=openssl --without-static-libpython --with-lto
      https://buildbot.python.org/all/#/builders/559/builds/1196

    @vstinner
    Copy link
    Member Author

    New changeset fda8886 by Victor Stinner in branch 'main':
    bpo-46417: Revert remove_subclass() change (GH-30750)
    fda8886

    @vstinner
    Copy link
    Member Author

    bpo-46417: Revert remove_subclass() change (GH-30750)

    Ok, this change fixed buildbots.

    I saw code in typeobject.c which uses a borrowed reference to tp_subclasses with a loop which can modify tp_subclasses. This code should be modified to hold a strong reference to tp_subclasses while accessing it.

    The test_mock_add_spec() test of test_unittest modifies the subclasses of many types and so is indirectly a stress tests for code accessing tp_subclasses. That's why the regression was only seen in this specific test.

    @vstinner
    Copy link
    Member Author

    New changeset acda9f3 by Miss Islington (bot) in branch '3.10':
    bpo-46417: Fix race condition on setting type __bases__ (GH-30788) (GH-30789)
    acda9f3

    @vstinner
    Copy link
    Member Author

    New changeset f1796f2 by Miss Islington (bot) in branch '3.9':
    bpo-46417: Fix race condition on setting type __bases__ (GH-30788) (GH-30790)
    f1796f2

    @vstinner
    Copy link
    Member Author

    New changeset 2d03b73 by Victor Stinner in branch 'main':
    bpo-46417: remove_subclass() clears tp_subclasses (GH-30793)
    2d03b73

    @vstinner
    Copy link
    Member Author

    New changeset 500c146 by Victor Stinner in branch 'main':
    bpo-46417: Clear more static types (GH-30796)
    500c146

    @vstinner
    Copy link
    Member Author

    New changeset 3a4c15b by Victor Stinner in branch 'main':
    bpo-46417: Cleanup typeobject.c code (GH-30795)
    3a4c15b

    @vstinner
    Copy link
    Member Author

    New changeset 6cacdb4 by Victor Stinner in branch 'main':
    bpo-46417: _PyTypes_FiniTypes() clears object and type (GH-30798)
    6cacdb4

    @vstinner
    Copy link
    Member Author

    Kumar Aditya: "The following patch further reduces the reference but not sure if it is correct (...)"

    Right! PyContext and PyHamt types were on my TODO list ;-) They are now cleared since this change:

    bpo-46417: Clear more static types (GH-30796)
    500c146

    It's similar to your change, but more complete :-)

    @vstinner
    Copy link
    Member Author

    Attached cannot_deallocate.patch explains why some static types cannot be deallocated. It lists (static) types which are not cleard properly at Python exit.

    Simplest example:
    ---

    $ ./python -c pass
    Cannot clear type 'object': it still has subclasses
    * EncodingMap
    * fieldnameiterator
    * formatteriterator
    * BaseException
    * _io._IOBase
    * _io._BytesIOBuffer
    * _io.IncrementalNewlineDecoder

    More complete example:
    ---

    $ ./python setup.py build
    running build
    (...)
    Cannot clear type 'types.GenericAlias': it still has subclasses
    * _CallableGenericAlias
    Cannot clear type 'tuple': it still has subclasses
    * datetime.IsoCalendarDate
    * DecimalTuple
    Cannot clear type 'staticmethod': it still has subclasses
    * abstractstaticmethod
    Cannot clear type 'property': it still has subclasses
    * abstractproperty
    Cannot clear type 'list': it still has subclasses
    * MyList
    Cannot clear type 'dict': it still has subclasses
    * collections.defaultdict
    * StgDict
    Cannot clear type 'classmethod': it still has subclasses
    * abstractclassmethod
    Cannot clear type 'type': it still has subclasses
    * ABCMeta
    * _ctypes.PyCStructType
    * _ctypes.UnionType
    * _ctypes.PyCPointerType
    * _ctypes.PyCArrayType
    * _ctypes.PyCSimpleType
    * _ctypes.PyCFuncPtrType
    Cannot clear type 'object': it still has subclasses
    * type
    * classmethod
    * dict
    * list
    * property
    * staticmethod
    * tuple
    * types.GenericAlias
    * EncodingMap
    * fieldnameiterator
    * formatteriterator
    * BaseException
    * ModuleSpec
    * FrozenImporter
    * _io._IOBase
    * _io._BytesIOBuffer
    * _io.IncrementalNewlineDecoder
    * _LoaderBasics
    * FileLoader
    * _abc._abc_data
    * ABC
    * Hashable
    * Awaitable
    * AsyncIterable
    * Iterable
    * Sized
    * Container
    * Callable
    * 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
    * _IterationGuard
    * WeakSet
    * _struct.Struct
    * _struct.unpack_iterator
    * datetime.date
    * datetime.time
    * datetime.timedelta
    * datetime.tzinfo
    * _pickle.Pdata
    * _pickle.PicklerMemoProxy
    * _pickle.UnpicklerMemoProxy
    * _pickle.Pickler
    * _pickle.Unpickler
    * _socket.socket
    * _asyncio.FutureIter
    * TaskStepMethWrapper
    * _RunningLoopHolder
    * _asyncio.Future
    * _xxsubinterpreters.ChannelID
    * matmulType
    * ipowType
    * awaitType
    * MethodDescriptorBase
    * GenericAlias
    * Generic
    * MethInstance
    * MethClass
    * MethStatic
    * _testcapi.HeapCType
    * _testcapi.ContainerNoGC
    * _curses.window
    * ossaudiodev.oss_audio_device
    * ossaudiodev.oss_mixer_device
    * _elementtree._element_iterator
    * xml.etree.ElementTree.TreeBuilder
    * xml.etree.ElementTree.Element
    * xml.etree.ElementTree.XMLParser
    * decimal.Decimal
    * decimal.Context
    * decimal.SignalDictMixin
    * decimal.ContextManager
    * Number
    * _multiprocessing.SemLock
    * xxlimited.Xxo
    * CArgObject
    * _ctypes.CThunkObject
    * _ctypes._CData
    * _ctypes.CField
    * _ctypes.DictRemover
    * _ctypes.StructParam_Type

    @vstinner
    Copy link
    Member Author

    New changeset f1bcdea by Victor Stinner in branch 'main':
    bpo-46417: Factorize _PyExc_InitTypes() code (GH-30804)
    f1bcdea

    @vstinner
    Copy link
    Member Author

    New changeset 621a45c by Victor Stinner in branch 'main':
    bpo-46417: Py_Finalize() clears static exceptioins (GH-30805)
    621a45c

    @vstinner
    Copy link
    Member Author

    New changeset 1626bf4 by Victor Stinner in branch 'main':
    bpo-46417: Clear Unicode static types at exit (GH-30806)
    1626bf4

    @vstinner
    Copy link
    Member Author

    New changeset 9c8e490 by Victor Stinner in branch 'main':
    bpo-46417: Clear _io module static objects at exit (GH-30807)
    9c8e490

    @vstinner
    Copy link
    Member Author

    New changeset 12f4ac3 by Victor Stinner in branch 'main':
    bpo-46417: Clear symtable identifiers at exit (GH-30809)
    12f4ac3

    @vstinner
    Copy link
    Member Author

    New changeset a1444f4 by Victor Stinner in branch 'main':
    bpo-46417: Fix _PyStaticType_Dealloc() (GH-30810)
    a1444f4

    @vstinner
    Copy link
    Member Author

    The _PyStaticType_Dealloc() function cannot call PyObject_ClearWeakRefs() if the refcount is not zero. I am not sure if it's a real issue or not. Maybe the weakref list must be cleared (release memory), but callbacks must not be called?

    @vstinner
    Copy link
    Member Author

    cannot_deallocate2.patch: updated patch to debug which types are not cleared at exit.

    @vstinner
    Copy link
    Member Author

    New changeset a1444f4 by Victor Stinner in branch 'main':
    bpo-46417: Fix _PyStaticType_Dealloc() (GH-30810)
    a1444f4

    At this commit, Py_Finalize() no longer leaks references. It exceeded my expectations, it even makes _Py_RefTotal negative :-D

        $ ./python -I -X showrefcount -c pass
        [-4 refs, 61 blocks]

    I'm not sure why it's negative, but bpo-46449 should be investigate first.

    @vstinner
    Copy link
    Member Author

    See also bpo-46476: Not all memory allocated by _Py_Quicken() is released at Python exit.

    @vstinner
    Copy link
    Member Author

    New changeset 976dec9 by Victor Stinner in branch 'main':
    bpo-46417: _PyList_Fini() clears indexerr (GH-30815)
    976dec9

    @vstinner
    Copy link
    Member Author

    See also bpo-46476: Not all memory allocated by _Py_Quicken() is released at Python exit.

    If you apply my workaround for bpo-46476:
    https://bugs.python.org/issue46476#msg411321

    Python no longer leaks any memory block at exit for the simplest command!

    $ ./python -I -X showrefcount -c pass
    [-5 refs, 0 blocks]

    Moreover, I modified deepfreeze to only freeze importlib._bootstrap and importlib._bootstrap_external. It confirms that bpo-46449 is causing the negative reference count, because with these additional local changes I get a positive _Py_RefTotal:

    $ ./python -I -X showrefcount -c pass
    [6 refs, 0 blocks]

    @vstinner
    Copy link
    Member Author

    New changeset 6c6a153 by Victor Stinner in branch 'main':
    bpo-46417: signal: move siginfo_type to the module state (GH-30964)
    6c6a153

    @vstinner
    Copy link
    Member Author

    I close the issue. I cleared most static types at exit. Following work can be done in bpo-40077 or other issues.

    @vstinner
    Copy link
    Member Author

    New changeset 9a24127 by Victor Stinner in branch 'main':
    bpo-46417: _PyStructSequence_FiniType() updates _Py_RefTotal (GH-30988)
    9a24127

    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    3.11 only security fixes interpreter-core (Objects, Python, Grammar, and Parser dirs)
    Projects
    None yet
    Development

    No branches or pull requests

    3 participants