@@ -1168,17 +1168,6 @@ inline void add_class_method(object& cls, const char *name_, const cpp_function
1168
1168
}
1169
1169
}
1170
1170
1171
- // Thread state manipulation C API should not be called while Python runtime is finalizing.
1172
- // For more detail see https://docs.python.org/3.7/c-api/init.html#c.PyEval_RestoreThread
1173
- // `is_finalizing()` provides a version agnostic way to check if runtime is finalizing.
1174
- inline bool is_finalizing () {
1175
- #if PY_VERSION_HEX >= 0x03070000
1176
- return _Py_IsFinalizing ();
1177
- #else
1178
- return false ;
1179
- #endif
1180
- }
1181
-
1182
1171
PYBIND11_NAMESPACE_END (detail)
1183
1172
1184
1173
// / Given a pointer to a member function, cast it to its `Derived` version.
@@ -2132,13 +2121,21 @@ class gil_scoped_acquire {
2132
2121
pybind11_fail (" scoped_acquire::dec_ref(): internal error!" );
2133
2122
#endif
2134
2123
PyThreadState_Clear (tstate);
2135
- if (! detail::is_finalizing () )
2124
+ if (active )
2136
2125
PyThreadState_DeleteCurrent ();
2137
2126
PYBIND11_TLS_DELETE_VALUE (detail::get_internals ().tstate );
2138
2127
release = false ;
2139
2128
}
2140
2129
}
2141
2130
2131
+ // / This method will disable the PyThreadState_DeleteCurrent call. This
2132
+ // / should be called if the interpreter is shutting down, as the thread
2133
+ // / deletion is not allowed during shutdown.
2134
+ // / (_Py_IsFinalizing() on Python 3.7+)
2135
+ PYBIND11_NOINLINE void disarm () {
2136
+ active = false ;
2137
+ }
2138
+
2142
2139
PYBIND11_NOINLINE ~gil_scoped_acquire () {
2143
2140
dec_ref ();
2144
2141
if (release)
@@ -2147,6 +2144,7 @@ class gil_scoped_acquire {
2147
2144
private:
2148
2145
PyThreadState *tstate = nullptr ;
2149
2146
bool release = true ;
2147
+ bool active = true ;
2150
2148
};
2151
2149
2152
2150
class gil_scoped_release {
@@ -2162,11 +2160,20 @@ class gil_scoped_release {
2162
2160
PYBIND11_TLS_DELETE_VALUE (key);
2163
2161
}
2164
2162
}
2163
+ //
2164
+ // / This method will disable the PyThreadState_DeleteCurrent call. This
2165
+ // / should be called if the interpreter is shutting down, as the thread
2166
+ // / deletion is not allowed during shutdown.
2167
+ // / (_Py_IsFinalizing() on Python 3.7+)
2168
+ PYBIND11_NOINLINE void disarm () {
2169
+ active = false ;
2170
+ }
2171
+
2165
2172
~gil_scoped_release () {
2166
2173
if (!tstate)
2167
2174
return ;
2168
2175
// `PyEval_RestoreThread()` should not be called if runtime is finalizing
2169
- if (! detail::is_finalizing () )
2176
+ if (active )
2170
2177
PyEval_RestoreThread (tstate);
2171
2178
if (disassoc) {
2172
2179
auto key = detail::get_internals ().tstate ;
@@ -2176,24 +2183,31 @@ class gil_scoped_release {
2176
2183
private:
2177
2184
PyThreadState *tstate;
2178
2185
bool disassoc;
2186
+ bool active = true ;
2179
2187
};
2180
2188
#elif defined(PYPY_VERSION)
2181
2189
class gil_scoped_acquire {
2182
2190
PyGILState_STATE state;
2183
2191
public:
2184
2192
gil_scoped_acquire () { state = PyGILState_Ensure (); }
2185
2193
~gil_scoped_acquire () { PyGILState_Release (state); }
2194
+ void disarm () {}
2186
2195
};
2187
2196
2188
2197
class gil_scoped_release {
2189
2198
PyThreadState *state;
2190
2199
public:
2191
2200
gil_scoped_release () { state = PyEval_SaveThread (); }
2192
2201
~gil_scoped_release () { PyEval_RestoreThread (state); }
2202
+ void disarm () {}
2193
2203
};
2194
2204
#else
2195
- class gil_scoped_acquire { };
2196
- class gil_scoped_release { };
2205
+ class gil_scoped_acquire {
2206
+ void disarm () {}
2207
+ };
2208
+ class gil_scoped_release {
2209
+ void disarm () {}
2210
+ };
2197
2211
#endif
2198
2212
2199
2213
error_already_set::~error_already_set () {
0 commit comments