Skip to content

Commit b53ff38

Browse files
committed
Try to fix exception translators issue on certain platforms
Also fix a couple more pedantic warings
1 parent 228e27f commit b53ff38

1 file changed

Lines changed: 35 additions & 21 deletions

File tree

include/pybind11/detail/internals.h

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ class thread_specific_storage {
8080
thread_specific_storage() {
8181
// NOLINTNEXTLINE(bugprone-assignment-in-if-condition)
8282
if (!PYBIND11_TLS_KEY_CREATE(key_)) {
83-
pybind11_fail("thread_local_storage constructor: could not initialize the TSS key!");
83+
pybind11_fail(
84+
"thread_specific_storage constructor: could not initialize the TSS key!");
8485
}
8586
}
8687

@@ -115,7 +116,7 @@ class thread_specific_storage {
115116
}
116117

117118
private:
118-
PYBIND11_TLS_KEY_INIT(mutable key_);
119+
PYBIND11_TLS_KEY_INIT(mutable key_)
119120
};
120121

121122
PYBIND11_NAMESPACE_BEGIN(detail)
@@ -476,7 +477,9 @@ inline object get_python_state_dict() {
476477
template <typename InternalsType>
477478
class internals_pp_manager {
478479
public:
479-
explicit internals_pp_manager(char const *id) : holder_id_(id) {}
480+
using on_fetch_function = void(InternalsType *);
481+
explicit internals_pp_manager(char const *id, on_fetch_function *on_fetch = nullptr)
482+
: holder_id_(id), on_fetch_(on_fetch) {}
480483

481484
/// Get the current pointer-to-pointer, allocating it if it does not already exist. May
482485
/// acquire the GIL. Will never return nullptr.
@@ -539,7 +542,7 @@ class internals_pp_manager {
539542
dict state_dict = get_python_state_dict();
540543
auto internals_obj
541544
= reinterpret_steal<object>(dict_getitemstringref(state_dict.ptr(), holder_id_));
542-
std::unique_ptr<InternalsType> *pp;
545+
std::unique_ptr<InternalsType> *pp = nullptr;
543546
if (internals_obj) {
544547
void *raw_ptr = PyCapsule_GetPointer(internals_obj.ptr(), /*name=*/nullptr);
545548
if (!raw_ptr) {
@@ -548,46 +551,57 @@ class internals_pp_manager {
548551
throw error_already_set();
549552
}
550553
pp = reinterpret_cast<std::unique_ptr<InternalsType> *>(raw_ptr);
554+
if (on_fetch_ && pp) {
555+
on_fetch_(pp->get());
556+
}
551557
} else {
552558
pp = new std::unique_ptr<InternalsType>;
559+
// NOLINTNEXTLINE(bugprone-casting-through-void)
553560
state_dict[holder_id_] = capsule(reinterpret_cast<void *>(pp));
554561
}
555562
return pp;
556563
}
557564

558565
char const *holder_id_ = nullptr;
566+
on_fetch_function *on_fetch_ = nullptr;
559567
#if PYBIND11_HAS_SUBINTERPRETER_SUPPORT
560568
thread_specific_storage<PyInterpreterState> last_istate_;
561569
thread_specific_storage<std::unique_ptr<InternalsType>> internals_tls_p_;
562570
#endif
563571
std::unique_ptr<InternalsType> *internals_singleton_pp_;
564572
};
565573

574+
inline void on_internals_fetch(internals *internals_ptr) {
575+
// If We loaded the internals through `state_dict`, our `error_already_set`
576+
// and `builtin_exception` may be different local classes than the ones set up in the
577+
// initial exception translator, below, so add another for our local exception classes.
578+
//
579+
// libstdc++ doesn't require this (types there are identified only by name)
580+
// libc++ with CPython doesn't require this (types are explicitly exported)
581+
// libc++ with PyPy still need it, awaiting further investigation
582+
if (internals_ptr) {
583+
#if !defined(__GLIBCXX__)
584+
for (auto et : internals_ptr->registered_exception_translators) {
585+
if (et == &translate_local_exception) {
586+
return;
587+
}
588+
}
589+
internals_ptr->registered_exception_translators.push_front(&translate_local_exception);
590+
#endif
591+
}
592+
}
593+
566594
inline internals_pp_manager<internals> &get_internals_pp_manager() {
567-
static internals_pp_manager<internals> internals_pp_manager(PYBIND11_INTERNALS_ID);
595+
static internals_pp_manager<internals> internals_pp_manager(PYBIND11_INTERNALS_ID,
596+
&on_internals_fetch);
568597
return internals_pp_manager;
569598
}
570599

571600
/// Return a reference to the current `internals` data
572601
PYBIND11_NOINLINE internals &get_internals() {
573602
auto &ppmgr = get_internals_pp_manager();
574603
auto &internals_ptr = *ppmgr.get_pp();
575-
if (internals_ptr) {
576-
// If We loaded the internals through `state_dict`, our `error_already_set`
577-
// and `builtin_exception` may be different local classes than the ones set up in the
578-
// initial exception translator, below, so add another for our local exception classes.
579-
//
580-
// libstdc++ doesn't require this (types there are identified only by name)
581-
// libc++ with CPython doesn't require this (types are explicitly exported)
582-
// libc++ with PyPy still need it, awaiting further investigation
583-
#if !defined(__GLIBCXX__)
584-
if (internals_ptr->registered_exception_translators.empty()
585-
|| internals_ptr->registered_exception_translators.front()
586-
!= &translate_local_exception) {
587-
internals_ptr->registered_exception_translators.push_front(&translate_local_exception);
588-
}
589-
#endif
590-
} else {
604+
if (!internals_ptr) {
591605
// Slow path, something needs fetched from the state dict or created
592606
gil_scoped_acquire_simple gil;
593607
error_scope err_scope;

0 commit comments

Comments
 (0)