1111
1212#include " ../pytypes.h"
1313
14+ // / Tracks the `internals` and `type_info` ABI version independent of the main library version.
15+ // /
16+ // / Some portions of the code use an ABI that is conditional depending on this
17+ // / version number. That allows ABI-breaking changes to be "pre-implemented".
18+ // / Once the default version number is incremented, the conditional logic that
19+ // / no longer applies can be removed. Additionally, users that need not
20+ // / maintain ABI compatibility can increase the version number in order to take
21+ // / advantage of any functionality/efficiency improvements that depend on the
22+ // / newer ABI.
23+ // /
24+ // / WARNING: If you choose to manually increase the ABI version, note that
25+ // / pybind11 may not be tested as thoroughly with a non-default ABI version, and
26+ // / further ABI-incompatible changes may be made before the ABI is officially
27+ // / changed to the new version.
28+ #ifndef PYBIND11_INTERNALS_VERSION
29+ # define PYBIND11_INTERNALS_VERSION 4
30+ #endif
31+
1432PYBIND11_NAMESPACE_BEGIN (PYBIND11_NAMESPACE)
1533
1634using ExceptionTranslator = void (*)(std::exception_ptr);
@@ -25,30 +43,58 @@ inline PyObject *make_object_base_type(PyTypeObject *metaclass);
2543// The old Python Thread Local Storage (TLS) API is deprecated in Python 3.7 in favor of the new
2644// Thread Specific Storage (TSS) API.
2745#if PY_VERSION_HEX >= 0x03070000
28- # define PYBIND11_TLS_KEY_INIT (var ) Py_tss_t *var = nullptr
29- # define PYBIND11_TLS_GET_VALUE (key ) PyThread_tss_get((key))
30- # define PYBIND11_TLS_REPLACE_VALUE (key, value ) PyThread_tss_set((key), (value))
31- # define PYBIND11_TLS_DELETE_VALUE (key ) PyThread_tss_set((key), nullptr )
32- # define PYBIND11_TLS_FREE (key ) PyThread_tss_free(key)
46+ // Avoid unnecessary allocation of `Py_tss_t`, since we cannot use
47+ // `Py_LIMITED_API` anyway.
48+ # if PYBIND11_INTERNALS_VERSION > 4
49+ # define PYBIND11_TLS_KEY_REF Py_tss_t &
50+ # ifdef __GNUC__
51+ // Clang on macOS warns due to `Py_tss_NEEDS_INIT` not specifying an initializer
52+ // for every field.
53+ # define PYBIND11_TLS_KEY_INIT (var ) \
54+ _Pragma (" GCC diagnostic push" ) /* */ \
55+ _Pragma(" GCC diagnostic ignored \" -Wmissing-field-initializers\" " ) /* */ \
56+ Py_tss_t var \
57+ = Py_tss_NEEDS_INIT; \
58+ _Pragma (" GCC diagnostic pop" )
59+ # else
60+ # define PYBIND11_TLS_KEY_INIT (var ) Py_tss_t var = Py_tss_NEEDS_INIT;
61+ # endif
62+ # define PYBIND11_TLS_KEY_CREATE (var ) (PyThread_tss_create(&(var)) == 0 )
63+ # define PYBIND11_TLS_GET_VALUE (key ) PyThread_tss_get(&(key))
64+ # define PYBIND11_TLS_REPLACE_VALUE (key, value ) PyThread_tss_set(&(key), (value))
65+ # define PYBIND11_TLS_DELETE_VALUE (key ) PyThread_tss_set(&(key), nullptr )
66+ # define PYBIND11_TLS_FREE (key ) PyThread_tss_delete(&(key))
67+ # else
68+ # define PYBIND11_TLS_KEY_REF Py_tss_t *
69+ # define PYBIND11_TLS_KEY_INIT (var ) Py_tss_t *var = nullptr ;
70+ # define PYBIND11_TLS_KEY_CREATE (var ) \
71+ (((var) = PyThread_tss_alloc()) != nullptr && (PyThread_tss_create((var)) == 0 ))
72+ # define PYBIND11_TLS_GET_VALUE (key ) PyThread_tss_get((key))
73+ # define PYBIND11_TLS_REPLACE_VALUE (key, value ) PyThread_tss_set((key), (value))
74+ # define PYBIND11_TLS_DELETE_VALUE (key ) PyThread_tss_set((key), nullptr )
75+ # define PYBIND11_TLS_FREE (key ) PyThread_tss_free(key)
76+ # endif
3377#else
34- // Usually an int but a long on Cygwin64 with Python 3.x
35- # define PYBIND11_TLS_KEY_INIT (var ) decltype (PyThread_create_key()) var = 0
78+ // Usually an int but a long on Cygwin64 with Python 3.x
79+ # define PYBIND11_TLS_KEY_REF decltype (PyThread_create_key())
80+ # define PYBIND11_TLS_KEY_INIT (var ) PYBIND11_TLS_KEY_REF var = 0 ;
81+ # define PYBIND11_TLS_KEY_CREATE (var ) (((var) = PyThread_create_key()) != -1 )
3682# define PYBIND11_TLS_GET_VALUE (key ) PyThread_get_key_value((key))
37- # if PY_MAJOR_VERSION < 3
38- # define PYBIND11_TLS_DELETE_VALUE (key ) \
39- PyThread_delete_key_value (key)
40- # define PYBIND11_TLS_REPLACE_VALUE (key, value ) \
41- do { \
42- PyThread_delete_key_value ((key)); \
43- PyThread_set_key_value ((key), (value)); \
44- } while (false )
83+ # if PY_MAJOR_VERSION < 3 || defined(PYPY_VERSION)
84+ // On CPython < 3.4 and on PyPy, `PyThread_set_key_value` strangely does not set
85+ // the value if it has already been set. Instead, it must first be deleted and
86+ // then set again.
87+ # define PYBIND11_TLS_DELETE_VALUE (key ) PyThread_delete_key_value(key)
88+ # define PYBIND11_TLS_REPLACE_VALUE (key, value ) \
89+ do { \
90+ PyThread_delete_key_value ((key)); \
91+ PyThread_set_key_value ((key), (value)); \
92+ } while (false )
4593# else
46- # define PYBIND11_TLS_DELETE_VALUE (key ) \
47- PyThread_set_key_value ((key), nullptr)
48- # define PYBIND11_TLS_REPLACE_VALUE (key, value ) \
49- PyThread_set_key_value ((key), (value))
94+ # define PYBIND11_TLS_DELETE_VALUE (key ) PyThread_set_key_value((key), nullptr )
95+ # define PYBIND11_TLS_REPLACE_VALUE (key, value ) PyThread_set_key_value((key), (value))
5096# endif
51- # define PYBIND11_TLS_FREE (key ) (void )key
97+ # define PYBIND11_TLS_FREE (key ) (void ) key
5298#endif
5399
54100// Python loads modules by default with dlopen with the RTLD_LOCAL flag; under libc++ and possibly
@@ -106,22 +152,31 @@ struct internals {
106152 std::unordered_map<const PyObject *, std::vector<PyObject *>> patients;
107153 std::forward_list<ExceptionTranslator> registered_exception_translators;
108154 std::unordered_map<std::string, void *> shared_data; // Custom data to be shared across extensions
155+ #if PYBIND11_INTERNALS_VERSION == 4
109156 std::vector<PyObject *> unused_loader_patient_stack_remove_at_v5;
157+ #endif
110158 std::forward_list<std::string> static_strings; // Stores the std::strings backing detail::c_str()
111159 PyTypeObject *static_property_type;
112160 PyTypeObject *default_metaclass;
113161 PyObject *instance_base;
114162#if defined(WITH_THREAD)
115- PYBIND11_TLS_KEY_INIT (tstate);
163+ PYBIND11_TLS_KEY_INIT (tstate)
164+ # if PYBIND11_INTERNALS_VERSION > 4
165+ PYBIND11_TLS_KEY_INIT (loader_life_support_tls_key)
166+ # endif // PYBIND11_INTERNALS_VERSION > 4
116167 PyInterpreterState *istate = nullptr ;
117168 ~internals () {
169+ # if PYBIND11_INTERNALS_VERSION > 4
170+ PYBIND11_TLS_FREE (loader_life_support_tls_key);
171+ # endif // PYBIND11_INTERNALS_VERSION > 4
172+
118173 // This destructor is called *after* Py_Finalize() in finalize_interpreter().
119- // That *SHOULD BE* fine. The following details what happens when PyThread_tss_free is called.
120- // PYBIND11_TLS_FREE is PyThread_tss_free on python 3.7+. On older python, it does nothing.
121- // PyThread_tss_free calls PyThread_tss_delete and PyMem_RawFree.
122- // PyThread_tss_delete just calls TlsFree (on Windows) or pthread_key_delete (on *NIX). Neither
123- // of those have anything to do with CPython internals.
124- // PyMem_RawFree *requires* that the `tstate` be allocated with the CPython allocator.
174+ // That *SHOULD BE* fine. The following details what happens when PyThread_tss_free is
175+ // called. PYBIND11_TLS_FREE is PyThread_tss_free on python 3.7+. On older python, it does
176+ // nothing. PyThread_tss_free calls PyThread_tss_delete and PyMem_RawFree.
177+ // PyThread_tss_delete just calls TlsFree (on Windows) or pthread_key_delete (on *NIX).
178+ // Neither of those have anything to do with CPython internals. PyMem_RawFree *requires*
179+ // that the `tstate` be allocated with the CPython allocator.
125180 PYBIND11_TLS_FREE (tstate);
126181 }
127182#endif
@@ -153,9 +208,6 @@ struct type_info {
153208 bool module_local : 1 ;
154209};
155210
156- // / Tracks the `internals` and `type_info` ABI version independent of the main library version
157- #define PYBIND11_INTERNALS_VERSION 4
158-
159211// / On MSVC, debug and release builds are not ABI-compatible!
160212#if defined(_MSC_VER) && defined(_DEBUG)
161213# define PYBIND11_BUILD_TYPE " _debug"
@@ -291,21 +343,21 @@ PYBIND11_NOINLINE internals &get_internals() {
291343 internals_ptr = new internals ();
292344#if defined(WITH_THREAD)
293345
294- # if PY_VERSION_HEX < 0x03090000
295- PyEval_InitThreads ();
296- # endif
346+ # if PY_VERSION_HEX < 0x03090000
347+ PyEval_InitThreads ();
348+ # endif
297349 PyThreadState *tstate = PyThreadState_Get ();
298- # if PY_VERSION_HEX >= 0x03070000
299- internals_ptr-> tstate = PyThread_tss_alloc ( );
300- if (!internals_ptr-> tstate || ( PyThread_tss_create (internals_ptr-> tstate ) != 0 ))
301- pybind11_fail ( " get_internals: could not successfully initialize the tstate TSS key! " );
302- PyThread_tss_set (internals_ptr-> tstate , tstate);
303- # else
304- internals_ptr->tstate = PyThread_create_key ();
305- if (internals_ptr-> tstate == - 1 )
306- pybind11_fail ( " get_internals: could not successfully initialize the tstate TLS key!" );
307- PyThread_set_key_value (internals_ptr-> tstate , tstate);
308- # endif
350+ if (! PYBIND11_TLS_KEY_CREATE (internals_ptr-> tstate )) {
351+ pybind11_fail ( " get_internals: could not successfully initialize the tstate TSS key! " );
352+ }
353+ PYBIND11_TLS_REPLACE_VALUE (internals_ptr-> tstate , tstate );
354+
355+ # if PYBIND11_INTERNALS_VERSION > 4
356+ if (! PYBIND11_TLS_KEY_CREATE ( internals_ptr->loader_life_support_tls_key )) {
357+ pybind11_fail ( " get_internals: could not successfully initialize the "
358+ " loader_life_support TSS key!" );
359+ }
360+ # endif
309361 internals_ptr->istate = tstate->interp ;
310362#endif
311363 builtins[id] = capsule (internals_pp);
@@ -317,16 +369,48 @@ PYBIND11_NOINLINE internals &get_internals() {
317369 return **internals_pp;
318370}
319371
320-
321372// the internals struct (above) is shared between all the modules. local_internals are only
322373// for a single module. Any changes made to internals may require an update to
323374// PYBIND11_INTERNALS_VERSION, breaking backwards compatibility. local_internals is, by design,
324375// restricted to a single module. Whether a module has local internals or not should not
325376// impact any other modules, because the only things accessing the local internals is the
326377// module that contains them.
327378struct local_internals {
328- type_map<type_info *> registered_types_cpp;
329- std::forward_list<ExceptionTranslator> registered_exception_translators;
379+ type_map<type_info *> registered_types_cpp;
380+ std::forward_list<ExceptionTranslator> registered_exception_translators;
381+ #if defined(WITH_THREAD) && PYBIND11_INTERNALS_VERSION == 4
382+
383+ // For ABI compatibility, we can't store the loader_life_support TLS key in
384+ // the `internals` struct directly. Instead, we store it in `shared_data` and
385+ // cache a copy in `local_internals`. If we allocated a separate TLS key for
386+ // each instance of `local_internals`, we could end up allocating hundreds of
387+ // TLS keys if hundreds of different pybind11 modules are loaded (which is a
388+ // plausible number).
389+ PYBIND11_TLS_KEY_INIT (loader_life_support_tls_key)
390+
391+ // Holds the shared TLS key for the loader_life_support stack.
392+ struct shared_loader_life_support_data {
393+ PYBIND11_TLS_KEY_INIT (loader_life_support_tls_key)
394+ shared_loader_life_support_data () {
395+ if (!PYBIND11_TLS_KEY_CREATE (loader_life_support_tls_key)) {
396+ pybind11_fail (" local_internals: could not successfully initialize the "
397+ " loader_life_support TLS key!" );
398+ }
399+ }
400+ // We can't help but leak the TLS key, because Python never unloads extension modules.
401+ };
402+
403+ local_internals () {
404+ auto &internals = get_internals ();
405+ // Get or create the `loader_life_support_stack_key`.
406+ auto &ptr = internals.shared_data [" _life_support" ];
407+ if (!ptr) {
408+ ptr = new shared_loader_life_support_data;
409+ }
410+ loader_life_support_tls_key
411+ = static_cast <shared_loader_life_support_data *>(ptr)->loader_life_support_tls_key ;
412+ }
413+ #endif // defined(WITH_THREAD) && PYBIND11_INTERNALS_VERSION == 4
330414};
331415
332416// / Works like `get_internals`, but for things which are locally registered.
0 commit comments