[subinterpreters] Static types incorrectly share some objects between interpreters #94673
Description
While static types (PyTypeObject values) don't themselves ever change (once PyType_Ready() has run), they do hold mutable data. This means they cannot be safely shared between multiple interpreters without a common GIL (and without state leaking between).
Mutable data:
- the object header (e.g. refcount), as with all objects
- otherwise immutable objects:
- ob_type (
__class__) - tp_base (
__base__) - set byPyType_Ready()if not set - tp_bases (
__bases__) - always set byPyType_Ready() - tp_mro (
__mro__) - always set byPyType_Ready() - tp_dict (
__dict__) - set byPyType_Ready()if not set
- ob_type (
- mutable containers:
- tp_subclasses (
__subclasses__) - tp_weaklist
- tp_subclasses (
(See https://docs.python.org/3/c-api/typeobj.html#tp-slots.)
(Note that tp_cache is no longer used.)
For the object header, if PEP 683 (immortal objects) is accepted then we can make static types immortal.
For the otherwise immutable objects, we can make sure each is immortal and then we're good. Even tp_dict is fine since it gets hidden behind types.MappingProxyType. We'd also need to either make sure each contained item is immortal.
For tp_subclasses we will need a per-interpreter copy, and do the proper lookup in the __subclasses__ getter. The cache could be stored on PyInterpreterState or even as a dict in tp_subclasses.
For tp_weaklist it's a similar story as for tp_subclasses. Note that tp_weaklist isn't very important for static types since they are never deallocated.
(The above is also discussed in PEP 684.)
Linked PRs
- gh-94673: Isolate the _io module to Each Interpreter #102663
- gh-94673: More Per-Interpreter Fields for Builtin Static Types #103912
- gh-94673: Ensure Builtin Static Types are Readied Properly #103940
- gh-94673: Fix _PyTypes_InitTypes() and get_type_attr_as_size() #103961
- gh-94673: Properly Initialize and Finalize Static Builtin Types for Each Interpreter #104072
- gh-94673: Hide Objects in PyTypeObject Behind Accessors #104074
- gh-94673: Ensure subtypes are readied only once in math.trunc() #105465
- [3.12] gh-94673: Ensure subtypes are readied only once in math.trunc() (gh-105465) #105471
- gh-94673: Clarify About Runtime State Related to Static Builtin Types #117761
- gh-94673: Fix compiler warning in typeobject.c #117980
Metadata
Metadata
Assignees
Labels
Projects
- StatusShow more project fieldsDone
Activity
ericsnowcurrently commentedon Jul 9, 2022
See https://peps.python.org/pep-0684/#global-objects.
kumaraditya303 commentedon Jul 10, 2022
The current
_PyInterpreterState_GET(which would be used here) static inline function is quite inefficient as there is a lot indirection and involves atomic reads to get the "current" thread and then get the interpreter state. To improve this we can use thread local 1 variables on supported platform such as Linux, Windows and macOS. On Linux with glibc, the thread local implementation uses fs segment register and on x86-64 it is very efficient compared to the current implementation.This isn't required here but would be nice to investigate separately.
Footnotes
https://en.cppreference.com/w/c/thread/thread_local ↩
encukou commentedon Jul 11, 2022
Python currently has a common GIL.
Shouldn't this be part of a PEP, rather than an issue?
gh-94673: [c-analyzer] Add a Script to Identify Static Types (#94989)
ericsnowcurrently commentedon Jul 19, 2022
I have the changes ready for this:
tp_subclassesto that statetp_weaklistto that state28 remaining items
Merge branch 'main' into inlinecomp2
Merge branch 'main' into cached_property_docs
gh-94673: More Per-Interpreter Fields for Builtin Static Types (gh-10…
gh-94673: Ensure subtypes are readied only once in math.trunc() (gh-1…
pythongh-94673: Ensure subtypes are readied only once in math.trunc() (…
[3.12] gh-94673: Ensure subtypes are readied only once in math.trunc() (
gh-94673: Clarify About Runtime State Related to Static Builtin Types (…
gvanrossum commentedon Apr 15, 2024
We now get a warning when building without pydebug:
ericsnowcurrently commentedon Apr 16, 2024
I'll take a look.
pythongh-94673: Clarify About Runtime State Related to Static Builtin…
pythongh-94673: Fix compiler warning in typeobject.c
gh-94673: Fix compiler warning in typeobject.c (#117980)
golang_str: Fix SIGSEGV on import on py3.12
golang_str: Fix infrastructure to patch builtin types for py3.13+
heapyc & setsc: Lock static type initializations