Skip to content

Commit 2a4b118

Browse files
authored
Merge branch 'master' into subinterp-call-once-and-store
2 parents 0bac82d + 5b37916 commit 2a4b118

File tree

2 files changed

+23
-17
lines changed

2 files changed

+23
-17
lines changed

include/pybind11/pytypes.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,8 +547,13 @@ struct error_fetch_and_normalize {
547547
// The presence of __notes__ is likely due to exception normalization
548548
// errors, although that is not necessarily true, therefore insert a
549549
// hint only:
550-
if (PyObject_HasAttrString(m_value.ptr(), "__notes__") != 0) {
550+
const int has_notes = PyObject_HasAttrString(m_value.ptr(), "__notes__");
551+
if (has_notes == 1) {
551552
m_lazy_error_string += "[WITH __notes__]";
553+
} else if (has_notes == -1) {
554+
// Ignore secondary errors when probing for __notes__ to avoid leaking a
555+
// spurious exception while still reporting the original error.
556+
PyErr_Clear();
552557
}
553558
#else
554559
// PyErr_NormalizeException() may change the exception type if there are cascading

include/pybind11/subinterpreter.h

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@
2222
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
2323
PYBIND11_NAMESPACE_BEGIN(detail)
2424
inline PyInterpreterState *get_interpreter_state_unchecked() {
25-
auto cur_tstate = get_thread_state_unchecked();
26-
if (cur_tstate)
25+
auto *cur_tstate = get_thread_state_unchecked();
26+
if (cur_tstate) {
2727
return cur_tstate->interp;
28-
else
29-
return nullptr;
28+
}
29+
return nullptr;
3030
}
3131
PYBIND11_NAMESPACE_END(detail)
3232

@@ -76,15 +76,15 @@ class subinterpreter {
7676
/// Create a new subinterpreter with the specified configuration
7777
/// @note This function acquires (and then releases) the main interpreter GIL, but the main
7878
/// interpreter and its GIL are not required to be held prior to calling this function.
79-
static inline subinterpreter create(PyInterpreterConfig const &cfg) {
79+
static subinterpreter create(PyInterpreterConfig const &cfg) {
8080

8181
error_scope err_scope;
8282
subinterpreter result;
8383
{
8484
// we must hold the main GIL in order to create a subinterpreter
8585
subinterpreter_scoped_activate main_guard(main());
8686

87-
auto prev_tstate = PyThreadState_Get();
87+
auto *prev_tstate = PyThreadState_Get();
8888

8989
PyStatus status;
9090

@@ -103,7 +103,7 @@ class subinterpreter {
103103
}
104104

105105
// this doesn't raise a normal Python exception, it provides an exit() status code.
106-
if (PyStatus_Exception(status)) {
106+
if (PyStatus_Exception(status) != 0) {
107107
pybind11_fail("failed to create new sub-interpreter");
108108
}
109109

@@ -128,7 +128,7 @@ class subinterpreter {
128128

129129
/// Calls create() with a default configuration of an isolated interpreter that disallows fork,
130130
/// exec, and Python threads.
131-
static inline subinterpreter create() {
131+
static subinterpreter create() {
132132
// same as the default config in the python docs
133133
PyInterpreterConfig cfg;
134134
std::memset(&cfg, 0, sizeof(cfg));
@@ -144,8 +144,8 @@ class subinterpreter {
144144
return;
145145
}
146146

147-
PyThreadState *destroy_tstate;
148-
PyThreadState *old_tstate;
147+
PyThreadState *destroy_tstate = nullptr;
148+
PyThreadState *old_tstate = nullptr;
149149

150150
// Python 3.12 requires us to keep the original PyThreadState alive until we are ready to
151151
// destroy the interpreter. We prefer to use that to destroy the interpreter.
@@ -173,7 +173,7 @@ class subinterpreter {
173173
old_tstate = PyThreadState_Swap(destroy_tstate);
174174
#endif
175175

176-
bool switch_back = old_tstate && old_tstate->interp != istate_;
176+
bool switch_back = (old_tstate != nullptr) && old_tstate->interp != istate_;
177177

178178
// Internals always exists in the subinterpreter, this class enforces it when it creates
179179
// the subinterpreter. Even if it didn't, this only creates the pointer-to-pointer, not the
@@ -190,8 +190,9 @@ class subinterpreter {
190190
detail::get_local_internals_pp_manager().destroy();
191191

192192
// switch back to the old tstate and old GIL (if there was one)
193-
if (switch_back)
193+
if (switch_back) {
194194
PyThreadState_Swap(old_tstate);
195+
}
195196
}
196197

197198
/// Get a handle to the main interpreter that can be used with subinterpreter_scoped_activate
@@ -214,11 +215,11 @@ class subinterpreter {
214215

215216
/// Get the numerical identifier for the sub-interpreter
216217
int64_t id() const {
217-
if (istate_ != nullptr)
218+
if (istate_ != nullptr) {
218219
return PyInterpreterState_GetID(istate_);
219-
else
220-
return -1; // CPython uses one-up numbers from 0, so negative should be safe to return
221-
// here.
220+
}
221+
return -1; // CPython uses one-up numbers from 0, so negative should be safe to return
222+
// here.
222223
}
223224

224225
/// Get the interpreter's state dict. This interpreter's GIL must be held before calling!

0 commit comments

Comments
 (0)